Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ afbaa7b4

History | View | Annotate | Download (23.5 kB)

1 53c25cea Paul Brook
/*
2 53c25cea Paul Brook
 * Virtio PCI Bindings
3 53c25cea Paul Brook
 *
4 53c25cea Paul Brook
 * Copyright IBM, Corp. 2007
5 53c25cea Paul Brook
 * Copyright (c) 2009 CodeSourcery
6 53c25cea Paul Brook
 *
7 53c25cea Paul Brook
 * Authors:
8 53c25cea Paul Brook
 *  Anthony Liguori   <aliguori@us.ibm.com>
9 53c25cea Paul Brook
 *  Paul Brook        <paul@codesourcery.com>
10 53c25cea Paul Brook
 *
11 53c25cea Paul Brook
 * This work is licensed under the terms of the GNU GPL, version 2.  See
12 53c25cea Paul Brook
 * the COPYING file in the top-level directory.
13 53c25cea Paul Brook
 *
14 53c25cea Paul Brook
 */
15 53c25cea Paul Brook
16 53c25cea Paul Brook
#include <inttypes.h>
17 53c25cea Paul Brook
18 53c25cea Paul Brook
#include "virtio.h"
19 8172539d Michael S. Tsirkin
#include "virtio-blk.h"
20 8172539d Michael S. Tsirkin
#include "virtio-net.h"
21 53c25cea Paul Brook
#include "pci.h"
22 2f792016 Markus Armbruster
#include "qemu-error.h"
23 aba800a3 Michael S. Tsirkin
#include "msix.h"
24 a1e0fea5 Gerd Hoffmann
#include "net.h"
25 97b15621 Gerd Hoffmann
#include "loader.h"
26 ade80dc8 Michael S. Tsirkin
#include "kvm.h"
27 2446333c Blue Swirl
#include "blockdev.h"
28 53c25cea Paul Brook
29 53c25cea Paul Brook
/* from Linux's linux/virtio_pci.h */
30 53c25cea Paul Brook
31 53c25cea Paul Brook
/* A 32-bit r/o bitmask of the features supported by the host */
32 53c25cea Paul Brook
#define VIRTIO_PCI_HOST_FEATURES        0
33 53c25cea Paul Brook
34 53c25cea Paul Brook
/* A 32-bit r/w bitmask of features activated by the guest */
35 53c25cea Paul Brook
#define VIRTIO_PCI_GUEST_FEATURES       4
36 53c25cea Paul Brook
37 53c25cea Paul Brook
/* A 32-bit r/w PFN for the currently selected queue */
38 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_PFN            8
39 53c25cea Paul Brook
40 53c25cea Paul Brook
/* A 16-bit r/o queue size for the currently selected queue */
41 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NUM            12
42 53c25cea Paul Brook
43 53c25cea Paul Brook
/* A 16-bit r/w queue selector */
44 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_SEL            14
45 53c25cea Paul Brook
46 53c25cea Paul Brook
/* A 16-bit r/w queue notifier */
47 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NOTIFY         16
48 53c25cea Paul Brook
49 53c25cea Paul Brook
/* An 8-bit device status register.  */
50 53c25cea Paul Brook
#define VIRTIO_PCI_STATUS               18
51 53c25cea Paul Brook
52 53c25cea Paul Brook
/* An 8-bit r/o interrupt status register.  Reading the value will return the
53 53c25cea Paul Brook
 * current contents of the ISR and will also clear it.  This is effectively
54 53c25cea Paul Brook
 * a read-and-acknowledge. */
55 53c25cea Paul Brook
#define VIRTIO_PCI_ISR                  19
56 53c25cea Paul Brook
57 aba800a3 Michael S. Tsirkin
/* MSI-X registers: only enabled if MSI-X is enabled. */
58 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for configuration changes. */
59 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_CONFIG_VECTOR        20
60 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for selected queue notifications. */
61 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_QUEUE_VECTOR         22
62 aba800a3 Michael S. Tsirkin
63 aba800a3 Michael S. Tsirkin
/* Config space size */
64 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_NOMSI         20
65 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_MSI           24
66 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
67 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
68 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
69 aba800a3 Michael S. Tsirkin
70 aba800a3 Michael S. Tsirkin
/* The remaining space is defined by each driver as the per-driver
71 aba800a3 Michael S. Tsirkin
 * configuration space */
72 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
73 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
74 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
75 53c25cea Paul Brook
76 53c25cea Paul Brook
/* Virtio ABI version, if we increment this, we break the guest driver. */
77 53c25cea Paul Brook
#define VIRTIO_PCI_ABI_VERSION          0
78 53c25cea Paul Brook
79 53c25cea Paul Brook
/* How many bits to shift physical queue address written to QUEUE_PFN.
80 53c25cea Paul Brook
 * 12 is historical, and due to x86 page size. */
81 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
82 53c25cea Paul Brook
83 c81131db Alexander Graf
/* We can catch some guest bugs inside here so we continue supporting older
84 c81131db Alexander Graf
   guests. */
85 c81131db Alexander Graf
#define VIRTIO_PCI_BUG_BUS_MASTER        (1 << 0)
86 c81131db Alexander Graf
87 53c25cea Paul Brook
/* QEMU doesn't strictly need write barriers since everything runs in
88 53c25cea Paul Brook
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
89 53c25cea Paul Brook
 * KVM or if kqemu gets SMP support.
90 53c25cea Paul Brook
 */
91 53c25cea Paul Brook
#define wmb() do { } while (0)
92 53c25cea Paul Brook
93 53c25cea Paul Brook
/* PCI bindings.  */
94 53c25cea Paul Brook
95 53c25cea Paul Brook
typedef struct {
96 53c25cea Paul Brook
    PCIDevice pci_dev;
97 53c25cea Paul Brook
    VirtIODevice *vdev;
98 c81131db Alexander Graf
    uint32_t bugs;
99 53c25cea Paul Brook
    uint32_t addr;
100 ab73ff29 Gerd Hoffmann
    uint32_t class_code;
101 a1e0fea5 Gerd Hoffmann
    uint32_t nvectors;
102 428c149b Christoph Hellwig
    BlockConf block;
103 97b15621 Gerd Hoffmann
    NICConf nic;
104 8172539d Michael S. Tsirkin
    uint32_t host_features;
105 9f107513 Anthony Liguori
#ifdef CONFIG_LINUX
106 9f107513 Anthony Liguori
    V9fsConf fsconf;
107 9f107513 Anthony Liguori
#endif
108 98b19252 Amit Shah
    /* Max. number of ports we can have for a the virtio-serial device */
109 98b19252 Amit Shah
    uint32_t max_virtserial_ports;
110 f0c07c7c Alex Williamson
    virtio_net_conf net;
111 53c25cea Paul Brook
} VirtIOPCIProxy;
112 53c25cea Paul Brook
113 53c25cea Paul Brook
/* virtio device */
114 53c25cea Paul Brook
115 7055e687 Michael S. Tsirkin
static void virtio_pci_notify(void *opaque, uint16_t vector)
116 53c25cea Paul Brook
{
117 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
118 aba800a3 Michael S. Tsirkin
    if (msix_enabled(&proxy->pci_dev))
119 aba800a3 Michael S. Tsirkin
        msix_notify(&proxy->pci_dev, vector);
120 aba800a3 Michael S. Tsirkin
    else
121 aba800a3 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
122 53c25cea Paul Brook
}
123 53c25cea Paul Brook
124 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
125 ff24bd58 Michael S. Tsirkin
{
126 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
127 ff24bd58 Michael S. Tsirkin
    pci_device_save(&proxy->pci_dev, f);
128 ff24bd58 Michael S. Tsirkin
    msix_save(&proxy->pci_dev, f);
129 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
130 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, proxy->vdev->config_vector);
131 ff24bd58 Michael S. Tsirkin
}
132 ff24bd58 Michael S. Tsirkin
133 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
134 ff24bd58 Michael S. Tsirkin
{
135 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
136 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
137 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
138 ff24bd58 Michael S. Tsirkin
}
139 ff24bd58 Michael S. Tsirkin
140 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_config(void * opaque, QEMUFile *f)
141 ff24bd58 Michael S. Tsirkin
{
142 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
143 ff24bd58 Michael S. Tsirkin
    int ret;
144 ff24bd58 Michael S. Tsirkin
    ret = pci_device_load(&proxy->pci_dev, f);
145 e6da7680 Michael S. Tsirkin
    if (ret) {
146 ff24bd58 Michael S. Tsirkin
        return ret;
147 e6da7680 Michael S. Tsirkin
    }
148 ff24bd58 Michael S. Tsirkin
    msix_load(&proxy->pci_dev, f);
149 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
150 ff24bd58 Michael S. Tsirkin
        qemu_get_be16s(f, &proxy->vdev->config_vector);
151 e6da7680 Michael S. Tsirkin
    } else {
152 e6da7680 Michael S. Tsirkin
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
153 e6da7680 Michael S. Tsirkin
    }
154 e6da7680 Michael S. Tsirkin
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
155 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
156 e6da7680 Michael S. Tsirkin
    }
157 c81131db Alexander Graf
158 c81131db Alexander Graf
    /* Try to find out if the guest has bus master disabled, but is
159 c81131db Alexander Graf
       in ready state. Then we have a buggy guest OS. */
160 8a911107 Alex Williamson
    if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
161 c81131db Alexander Graf
        !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
162 c81131db Alexander Graf
        proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
163 c81131db Alexander Graf
    }
164 ff24bd58 Michael S. Tsirkin
    return 0;
165 ff24bd58 Michael S. Tsirkin
}
166 ff24bd58 Michael S. Tsirkin
167 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
168 ff24bd58 Michael S. Tsirkin
{
169 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
170 ff24bd58 Michael S. Tsirkin
    uint16_t vector;
171 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
172 e6da7680 Michael S. Tsirkin
        qemu_get_be16s(f, &vector);
173 e6da7680 Michael S. Tsirkin
    } else {
174 e6da7680 Michael S. Tsirkin
        vector = VIRTIO_NO_VECTOR;
175 e6da7680 Michael S. Tsirkin
    }
176 ff24bd58 Michael S. Tsirkin
    virtio_queue_set_vector(proxy->vdev, n, vector);
177 e6da7680 Michael S. Tsirkin
    if (vector != VIRTIO_NO_VECTOR) {
178 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, vector);
179 e6da7680 Michael S. Tsirkin
    }
180 ff24bd58 Michael S. Tsirkin
    return 0;
181 ff24bd58 Michael S. Tsirkin
}
182 ff24bd58 Michael S. Tsirkin
183 e489030d Michael S. Tsirkin
static void virtio_pci_reset(DeviceState *d)
184 7055e687 Michael S. Tsirkin
{
185 e489030d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
186 7055e687 Michael S. Tsirkin
    virtio_reset(proxy->vdev);
187 aba800a3 Michael S. Tsirkin
    msix_reset(&proxy->pci_dev);
188 c81131db Alexander Graf
    proxy->bugs = 0;
189 7055e687 Michael S. Tsirkin
}
190 7055e687 Michael S. Tsirkin
191 53c25cea Paul Brook
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
192 53c25cea Paul Brook
{
193 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
194 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
195 c227f099 Anthony Liguori
    target_phys_addr_t pa;
196 53c25cea Paul Brook
197 53c25cea Paul Brook
    switch (addr) {
198 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
199 53c25cea Paul Brook
        /* Guest does not negotiate properly?  We have to assume nothing. */
200 53c25cea Paul Brook
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
201 53c25cea Paul Brook
            if (vdev->bad_features)
202 8172539d Michael S. Tsirkin
                val = proxy->host_features & vdev->bad_features(vdev);
203 53c25cea Paul Brook
            else
204 53c25cea Paul Brook
                val = 0;
205 53c25cea Paul Brook
        }
206 53c25cea Paul Brook
        if (vdev->set_features)
207 53c25cea Paul Brook
            vdev->set_features(vdev, val);
208 704a76fc Michael S. Tsirkin
        vdev->guest_features = val;
209 53c25cea Paul Brook
        break;
210 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
211 c227f099 Anthony Liguori
        pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
212 1b8e9b27 Michael S. Tsirkin
        if (pa == 0) {
213 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
214 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
215 1b8e9b27 Michael S. Tsirkin
        }
216 7055e687 Michael S. Tsirkin
        else
217 7055e687 Michael S. Tsirkin
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
218 53c25cea Paul Brook
        break;
219 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
220 53c25cea Paul Brook
        if (val < VIRTIO_PCI_QUEUE_MAX)
221 53c25cea Paul Brook
            vdev->queue_sel = val;
222 53c25cea Paul Brook
        break;
223 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NOTIFY:
224 53c25cea Paul Brook
        virtio_queue_notify(vdev, val);
225 53c25cea Paul Brook
        break;
226 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
227 3e607cb5 Michael S. Tsirkin
        virtio_set_status(vdev, val & 0xFF);
228 1b8e9b27 Michael S. Tsirkin
        if (vdev->status == 0) {
229 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
230 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
231 1b8e9b27 Michael S. Tsirkin
        }
232 c81131db Alexander Graf
233 c81131db Alexander Graf
        /* Linux before 2.6.34 sets the device as OK without enabling
234 c81131db Alexander Graf
           the PCI device bus master bit. In this case we need to disable
235 c81131db Alexander Graf
           some safety checks. */
236 c81131db Alexander Graf
        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
237 c81131db Alexander Graf
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
238 c81131db Alexander Graf
            proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
239 c81131db Alexander Graf
        }
240 53c25cea Paul Brook
        break;
241 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
242 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
243 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
244 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
245 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
246 aba800a3 Michael S. Tsirkin
        vdev->config_vector = val;
247 aba800a3 Michael S. Tsirkin
        break;
248 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
249 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev,
250 aba800a3 Michael S. Tsirkin
                          virtio_queue_vector(vdev, vdev->queue_sel));
251 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
252 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
253 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
254 aba800a3 Michael S. Tsirkin
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
255 aba800a3 Michael S. Tsirkin
        break;
256 aba800a3 Michael S. Tsirkin
    default:
257 aba800a3 Michael S. Tsirkin
        fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n",
258 aba800a3 Michael S. Tsirkin
                __func__, addr, val);
259 aba800a3 Michael S. Tsirkin
        break;
260 53c25cea Paul Brook
    }
261 53c25cea Paul Brook
}
262 53c25cea Paul Brook
263 aba800a3 Michael S. Tsirkin
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
264 53c25cea Paul Brook
{
265 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
266 53c25cea Paul Brook
    uint32_t ret = 0xFFFFFFFF;
267 53c25cea Paul Brook
268 53c25cea Paul Brook
    switch (addr) {
269 53c25cea Paul Brook
    case VIRTIO_PCI_HOST_FEATURES:
270 8172539d Michael S. Tsirkin
        ret = proxy->host_features;
271 53c25cea Paul Brook
        break;
272 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
273 704a76fc Michael S. Tsirkin
        ret = vdev->guest_features;
274 53c25cea Paul Brook
        break;
275 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
276 53c25cea Paul Brook
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
277 53c25cea Paul Brook
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
278 53c25cea Paul Brook
        break;
279 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NUM:
280 53c25cea Paul Brook
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
281 53c25cea Paul Brook
        break;
282 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
283 53c25cea Paul Brook
        ret = vdev->queue_sel;
284 53c25cea Paul Brook
        break;
285 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
286 53c25cea Paul Brook
        ret = vdev->status;
287 53c25cea Paul Brook
        break;
288 53c25cea Paul Brook
    case VIRTIO_PCI_ISR:
289 53c25cea Paul Brook
        /* reading from the ISR also clears it. */
290 53c25cea Paul Brook
        ret = vdev->isr;
291 53c25cea Paul Brook
        vdev->isr = 0;
292 7055e687 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
293 53c25cea Paul Brook
        break;
294 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
295 aba800a3 Michael S. Tsirkin
        ret = vdev->config_vector;
296 aba800a3 Michael S. Tsirkin
        break;
297 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
298 aba800a3 Michael S. Tsirkin
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
299 aba800a3 Michael S. Tsirkin
        break;
300 53c25cea Paul Brook
    default:
301 53c25cea Paul Brook
        break;
302 53c25cea Paul Brook
    }
303 53c25cea Paul Brook
304 53c25cea Paul Brook
    return ret;
305 53c25cea Paul Brook
}
306 53c25cea Paul Brook
307 53c25cea Paul Brook
static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
308 53c25cea Paul Brook
{
309 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
310 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
311 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
312 aba800a3 Michael S. Tsirkin
    if (addr < config)
313 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
314 aba800a3 Michael S. Tsirkin
    addr -= config;
315 53c25cea Paul Brook
    return virtio_config_readb(proxy->vdev, addr);
316 53c25cea Paul Brook
}
317 53c25cea Paul Brook
318 53c25cea Paul Brook
static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
319 53c25cea Paul Brook
{
320 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
321 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
322 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
323 aba800a3 Michael S. Tsirkin
    if (addr < config)
324 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
325 aba800a3 Michael S. Tsirkin
    addr -= config;
326 53c25cea Paul Brook
    return virtio_config_readw(proxy->vdev, addr);
327 53c25cea Paul Brook
}
328 53c25cea Paul Brook
329 53c25cea Paul Brook
static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
330 53c25cea Paul Brook
{
331 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
332 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
333 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
334 aba800a3 Michael S. Tsirkin
    if (addr < config)
335 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
336 aba800a3 Michael S. Tsirkin
    addr -= config;
337 53c25cea Paul Brook
    return virtio_config_readl(proxy->vdev, addr);
338 53c25cea Paul Brook
}
339 53c25cea Paul Brook
340 53c25cea Paul Brook
static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
341 53c25cea Paul Brook
{
342 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
343 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
344 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
345 aba800a3 Michael S. Tsirkin
    if (addr < config) {
346 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
347 aba800a3 Michael S. Tsirkin
        return;
348 aba800a3 Michael S. Tsirkin
    }
349 aba800a3 Michael S. Tsirkin
    addr -= config;
350 53c25cea Paul Brook
    virtio_config_writeb(proxy->vdev, addr, val);
351 53c25cea Paul Brook
}
352 53c25cea Paul Brook
353 53c25cea Paul Brook
static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
354 53c25cea Paul Brook
{
355 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
356 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
357 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
358 aba800a3 Michael S. Tsirkin
    if (addr < config) {
359 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
360 aba800a3 Michael S. Tsirkin
        return;
361 aba800a3 Michael S. Tsirkin
    }
362 aba800a3 Michael S. Tsirkin
    addr -= config;
363 53c25cea Paul Brook
    virtio_config_writew(proxy->vdev, addr, val);
364 53c25cea Paul Brook
}
365 53c25cea Paul Brook
366 53c25cea Paul Brook
static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
367 53c25cea Paul Brook
{
368 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
369 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
370 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
371 aba800a3 Michael S. Tsirkin
    if (addr < config) {
372 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
373 aba800a3 Michael S. Tsirkin
        return;
374 aba800a3 Michael S. Tsirkin
    }
375 aba800a3 Michael S. Tsirkin
    addr -= config;
376 53c25cea Paul Brook
    virtio_config_writel(proxy->vdev, addr, val);
377 53c25cea Paul Brook
}
378 53c25cea Paul Brook
379 53c25cea Paul Brook
static void virtio_map(PCIDevice *pci_dev, int region_num,
380 6e355d90 Isaku Yamahata
                       pcibus_t addr, pcibus_t size, int type)
381 53c25cea Paul Brook
{
382 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
383 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
384 aba800a3 Michael S. Tsirkin
    unsigned config_len = VIRTIO_PCI_REGION_SIZE(pci_dev) + vdev->config_len;
385 53c25cea Paul Brook
386 53c25cea Paul Brook
    proxy->addr = addr;
387 53c25cea Paul Brook
388 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 1, virtio_pci_config_writeb, proxy);
389 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 2, virtio_pci_config_writew, proxy);
390 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 4, virtio_pci_config_writel, proxy);
391 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 1, virtio_pci_config_readb, proxy);
392 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 2, virtio_pci_config_readw, proxy);
393 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 4, virtio_pci_config_readl, proxy);
394 53c25cea Paul Brook
395 aba800a3 Michael S. Tsirkin
    if (vdev->config_len)
396 53c25cea Paul Brook
        vdev->get_config(vdev, vdev->config);
397 aba800a3 Michael S. Tsirkin
}
398 aba800a3 Michael S. Tsirkin
399 aba800a3 Michael S. Tsirkin
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
400 aba800a3 Michael S. Tsirkin
                                uint32_t val, int len)
401 aba800a3 Michael S. Tsirkin
{
402 ed757e14 Yan Vugenfirer
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
403 ed757e14 Yan Vugenfirer
404 ed757e14 Yan Vugenfirer
    if (PCI_COMMAND == address) {
405 ed757e14 Yan Vugenfirer
        if (!(val & PCI_COMMAND_MASTER)) {
406 c81131db Alexander Graf
            if (!(proxy->bugs & VIRTIO_PCI_BUG_BUS_MASTER)) {
407 3e607cb5 Michael S. Tsirkin
                virtio_set_status(proxy->vdev,
408 3e607cb5 Michael S. Tsirkin
                                  proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
409 c81131db Alexander Graf
            }
410 ed757e14 Yan Vugenfirer
        }
411 ed757e14 Yan Vugenfirer
    }
412 ed757e14 Yan Vugenfirer
413 aba800a3 Michael S. Tsirkin
    pci_default_write_config(pci_dev, address, val, len);
414 85352471 Michael S. Tsirkin
    msix_write_config(pci_dev, address, val, len);
415 53c25cea Paul Brook
}
416 53c25cea Paul Brook
417 6d74ca5a Michael S. Tsirkin
static unsigned virtio_pci_get_features(void *opaque)
418 6d74ca5a Michael S. Tsirkin
{
419 8172539d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
420 8172539d Michael S. Tsirkin
    return proxy->host_features;
421 6d74ca5a Michael S. Tsirkin
}
422 6d74ca5a Michael S. Tsirkin
423 ade80dc8 Michael S. Tsirkin
static void virtio_pci_guest_notifier_read(void *opaque)
424 ade80dc8 Michael S. Tsirkin
{
425 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = opaque;
426 ade80dc8 Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
427 ade80dc8 Michael S. Tsirkin
    if (event_notifier_test_and_clear(n)) {
428 ade80dc8 Michael S. Tsirkin
        virtio_irq(vq);
429 ade80dc8 Michael S. Tsirkin
    }
430 ade80dc8 Michael S. Tsirkin
}
431 ade80dc8 Michael S. Tsirkin
432 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
433 ade80dc8 Michael S. Tsirkin
{
434 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
435 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
436 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
437 ade80dc8 Michael S. Tsirkin
438 ade80dc8 Michael S. Tsirkin
    if (assign) {
439 ade80dc8 Michael S. Tsirkin
        int r = event_notifier_init(notifier, 0);
440 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
441 ade80dc8 Michael S. Tsirkin
            return r;
442 ade80dc8 Michael S. Tsirkin
        }
443 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
444 ade80dc8 Michael S. Tsirkin
                            virtio_pci_guest_notifier_read, NULL, vq);
445 ade80dc8 Michael S. Tsirkin
    } else {
446 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
447 ade80dc8 Michael S. Tsirkin
                            NULL, NULL, NULL);
448 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
449 ade80dc8 Michael S. Tsirkin
    }
450 ade80dc8 Michael S. Tsirkin
451 ade80dc8 Michael S. Tsirkin
    return 0;
452 ade80dc8 Michael S. Tsirkin
}
453 ade80dc8 Michael S. Tsirkin
454 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
455 ade80dc8 Michael S. Tsirkin
{
456 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
457 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
458 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
459 ade80dc8 Michael S. Tsirkin
    int r;
460 ade80dc8 Michael S. Tsirkin
    if (assign) {
461 ade80dc8 Michael S. Tsirkin
        r = event_notifier_init(notifier, 1);
462 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
463 ade80dc8 Michael S. Tsirkin
            return r;
464 ade80dc8 Michael S. Tsirkin
        }
465 ade80dc8 Michael S. Tsirkin
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
466 ade80dc8 Michael S. Tsirkin
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
467 ade80dc8 Michael S. Tsirkin
                                       n, assign);
468 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
469 ade80dc8 Michael S. Tsirkin
            event_notifier_cleanup(notifier);
470 ade80dc8 Michael S. Tsirkin
        }
471 ade80dc8 Michael S. Tsirkin
    } else {
472 ade80dc8 Michael S. Tsirkin
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
473 ade80dc8 Michael S. Tsirkin
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
474 ade80dc8 Michael S. Tsirkin
                                       n, assign);
475 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
476 ade80dc8 Michael S. Tsirkin
            return r;
477 ade80dc8 Michael S. Tsirkin
        }
478 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
479 ade80dc8 Michael S. Tsirkin
    }
480 ade80dc8 Michael S. Tsirkin
    return r;
481 ade80dc8 Michael S. Tsirkin
}
482 ade80dc8 Michael S. Tsirkin
483 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
484 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
485 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
486 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
487 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
488 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
489 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
490 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
491 ade80dc8 Michael S. Tsirkin
    .set_guest_notifier = virtio_pci_set_guest_notifier,
492 53c25cea Paul Brook
};
493 53c25cea Paul Brook
494 53c25cea Paul Brook
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
495 53c25cea Paul Brook
                            uint16_t vendor, uint16_t device,
496 53c25cea Paul Brook
                            uint16_t class_code, uint8_t pif)
497 53c25cea Paul Brook
{
498 53c25cea Paul Brook
    uint8_t *config;
499 53c25cea Paul Brook
    uint32_t size;
500 53c25cea Paul Brook
501 53c25cea Paul Brook
    proxy->vdev = vdev;
502 53c25cea Paul Brook
503 53c25cea Paul Brook
    config = proxy->pci_dev.config;
504 53c25cea Paul Brook
    pci_config_set_vendor_id(config, vendor);
505 53c25cea Paul Brook
    pci_config_set_device_id(config, device);
506 53c25cea Paul Brook
507 53c25cea Paul Brook
    config[0x08] = VIRTIO_PCI_ABI_VERSION;
508 53c25cea Paul Brook
509 53c25cea Paul Brook
    config[0x09] = pif;
510 53c25cea Paul Brook
    pci_config_set_class(config, class_code);
511 53c25cea Paul Brook
512 53c25cea Paul Brook
    config[0x2c] = vendor & 0xFF;
513 53c25cea Paul Brook
    config[0x2d] = (vendor >> 8) & 0xFF;
514 53c25cea Paul Brook
    config[0x2e] = vdev->device_id & 0xFF;
515 53c25cea Paul Brook
    config[0x2f] = (vdev->device_id >> 8) & 0xFF;
516 53c25cea Paul Brook
517 53c25cea Paul Brook
    config[0x3d] = 1;
518 53c25cea Paul Brook
519 5a1fc5e8 Michael S. Tsirkin
    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
520 aba800a3 Michael S. Tsirkin
        pci_register_bar(&proxy->pci_dev, 1,
521 aba800a3 Michael S. Tsirkin
                         msix_bar_size(&proxy->pci_dev),
522 0392a017 Isaku Yamahata
                         PCI_BASE_ADDRESS_SPACE_MEMORY,
523 aba800a3 Michael S. Tsirkin
                         msix_mmio_map);
524 aba800a3 Michael S. Tsirkin
    } else
525 aba800a3 Michael S. Tsirkin
        vdev->nvectors = 0;
526 aba800a3 Michael S. Tsirkin
527 ed757e14 Yan Vugenfirer
    proxy->pci_dev.config_write = virtio_write_config;
528 ed757e14 Yan Vugenfirer
529 aba800a3 Michael S. Tsirkin
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
530 53c25cea Paul Brook
    if (size & (size-1))
531 53c25cea Paul Brook
        size = 1 << qemu_fls(size);
532 53c25cea Paul Brook
533 0392a017 Isaku Yamahata
    pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
534 53c25cea Paul Brook
                           virtio_map);
535 53c25cea Paul Brook
536 53c25cea Paul Brook
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
537 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
538 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
539 8172539d Michael S. Tsirkin
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
540 53c25cea Paul Brook
}
541 53c25cea Paul Brook
542 81a322d4 Gerd Hoffmann
static int virtio_blk_init_pci(PCIDevice *pci_dev)
543 53c25cea Paul Brook
{
544 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
545 53c25cea Paul Brook
    VirtIODevice *vdev;
546 53c25cea Paul Brook
547 ab73ff29 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
548 ab73ff29 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
549 ab73ff29 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
550 53c25cea Paul Brook
551 428c149b Christoph Hellwig
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
552 ac0c14d7 Markus Armbruster
    if (!vdev) {
553 ac0c14d7 Markus Armbruster
        return -1;
554 ac0c14d7 Markus Armbruster
    }
555 177539e0 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
556 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
557 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
558 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_BLOCK,
559 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
560 177539e0 Gerd Hoffmann
    /* make the actual value visible */
561 177539e0 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
562 81a322d4 Gerd Hoffmann
    return 0;
563 21d58b57 Mark McLoughlin
}
564 21d58b57 Mark McLoughlin
565 0f457d91 Michael S. Tsirkin
static int virtio_exit_pci(PCIDevice *pci_dev)
566 0f457d91 Michael S. Tsirkin
{
567 0f457d91 Michael S. Tsirkin
    return msix_uninit(pci_dev);
568 0f457d91 Michael S. Tsirkin
}
569 0f457d91 Michael S. Tsirkin
570 56a14938 Gerd Hoffmann
static int virtio_blk_exit_pci(PCIDevice *pci_dev)
571 56a14938 Gerd Hoffmann
{
572 56a14938 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
573 56a14938 Gerd Hoffmann
574 9d0d3138 Alex Williamson
    virtio_blk_exit(proxy->vdev);
575 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(proxy->block.bs);
576 0f457d91 Michael S. Tsirkin
    return virtio_exit_pci(pci_dev);
577 56a14938 Gerd Hoffmann
}
578 56a14938 Gerd Hoffmann
579 98b19252 Amit Shah
static int virtio_serial_init_pci(PCIDevice *pci_dev)
580 21d58b57 Mark McLoughlin
{
581 d6beee99 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
582 85c2c735 Mark McLoughlin
    VirtIODevice *vdev;
583 85c2c735 Mark McLoughlin
584 d6beee99 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
585 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
586 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
587 d6beee99 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
588 d6beee99 Gerd Hoffmann
589 98b19252 Amit Shah
    vdev = virtio_serial_init(&pci_dev->qdev, proxy->max_virtserial_ports);
590 25fe3654 Amit Shah
    if (!vdev) {
591 25fe3654 Amit Shah
        return -1;
592 25fe3654 Amit Shah
    }
593 573fb60c Amit Shah
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
594 573fb60c Amit Shah
                                        ? proxy->max_virtserial_ports + 1
595 573fb60c Amit Shah
                                        : proxy->nvectors;
596 85c2c735 Mark McLoughlin
    virtio_init_pci(proxy, vdev,
597 85c2c735 Mark McLoughlin
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
598 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_CONSOLE,
599 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
600 a1829205 Amit Shah
    proxy->nvectors = vdev->nvectors;
601 81a322d4 Gerd Hoffmann
    return 0;
602 53c25cea Paul Brook
}
603 53c25cea Paul Brook
604 8b53a865 Amit Shah
static int virtio_serial_exit_pci(PCIDevice *pci_dev)
605 8b53a865 Amit Shah
{
606 8b53a865 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
607 8b53a865 Amit Shah
608 8b53a865 Amit Shah
    virtio_serial_exit(proxy->vdev);
609 8b53a865 Amit Shah
    return virtio_exit_pci(pci_dev);
610 8b53a865 Amit Shah
}
611 8b53a865 Amit Shah
612 81a322d4 Gerd Hoffmann
static int virtio_net_init_pci(PCIDevice *pci_dev)
613 53c25cea Paul Brook
{
614 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
615 53c25cea Paul Brook
    VirtIODevice *vdev;
616 53c25cea Paul Brook
617 f0c07c7c Alex Williamson
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
618 a1e0fea5 Gerd Hoffmann
619 97b15621 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
620 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
621 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
622 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_NET,
623 53c25cea Paul Brook
                    PCI_CLASS_NETWORK_ETHERNET,
624 53c25cea Paul Brook
                    0x00);
625 a1e0fea5 Gerd Hoffmann
626 a1e0fea5 Gerd Hoffmann
    /* make the actual value visible */
627 a1e0fea5 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
628 81a322d4 Gerd Hoffmann
    return 0;
629 53c25cea Paul Brook
}
630 53c25cea Paul Brook
631 97b15621 Gerd Hoffmann
static int virtio_net_exit_pci(PCIDevice *pci_dev)
632 97b15621 Gerd Hoffmann
{
633 97b15621 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
634 97b15621 Gerd Hoffmann
635 97b15621 Gerd Hoffmann
    virtio_net_exit(proxy->vdev);
636 97b15621 Gerd Hoffmann
    return virtio_exit_pci(pci_dev);
637 97b15621 Gerd Hoffmann
}
638 97b15621 Gerd Hoffmann
639 81a322d4 Gerd Hoffmann
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
640 53c25cea Paul Brook
{
641 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
642 53c25cea Paul Brook
    VirtIODevice *vdev;
643 53c25cea Paul Brook
644 53c25cea Paul Brook
    vdev = virtio_balloon_init(&pci_dev->qdev);
645 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
646 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
647 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_BALLOON,
648 53c25cea Paul Brook
                    PCI_CLASS_MEMORY_RAM,
649 53c25cea Paul Brook
                    0x00);
650 81a322d4 Gerd Hoffmann
    return 0;
651 53c25cea Paul Brook
}
652 53c25cea Paul Brook
653 758e8e38 Venkateswararao Jujjuri (JV)
#ifdef CONFIG_VIRTFS
654 9f107513 Anthony Liguori
static int virtio_9p_init_pci(PCIDevice *pci_dev)
655 9f107513 Anthony Liguori
{
656 9f107513 Anthony Liguori
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
657 9f107513 Anthony Liguori
    VirtIODevice *vdev;
658 9f107513 Anthony Liguori
659 9f107513 Anthony Liguori
    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
660 9f107513 Anthony Liguori
    virtio_init_pci(proxy, vdev,
661 9f107513 Anthony Liguori
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
662 9f107513 Anthony Liguori
                    0x1009,
663 9f107513 Anthony Liguori
                    0x2,
664 9f107513 Anthony Liguori
                    0x00);
665 9f107513 Anthony Liguori
666 9f107513 Anthony Liguori
    return 0;
667 9f107513 Anthony Liguori
}
668 9f107513 Anthony Liguori
#endif
669 9f107513 Anthony Liguori
670 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo virtio_info[] = {
671 0aab0d3a Gerd Hoffmann
    {
672 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-blk-pci",
673 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
674 0aab0d3a Gerd Hoffmann
        .init      = virtio_blk_init_pci,
675 56a14938 Gerd Hoffmann
        .exit      = virtio_blk_exit_pci,
676 ab73ff29 Gerd Hoffmann
        .qdev.props = (Property[]) {
677 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
678 428c149b Christoph Hellwig
            DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
679 177539e0 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
680 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
681 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
682 ab73ff29 Gerd Hoffmann
        },
683 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
684 0aab0d3a Gerd Hoffmann
    },{
685 a1e0fea5 Gerd Hoffmann
        .qdev.name  = "virtio-net-pci",
686 a1e0fea5 Gerd Hoffmann
        .qdev.size  = sizeof(VirtIOPCIProxy),
687 a1e0fea5 Gerd Hoffmann
        .init       = virtio_net_init_pci,
688 97b15621 Gerd Hoffmann
        .exit       = virtio_net_exit_pci,
689 8c52c8f3 Gerd Hoffmann
        .romfile    = "pxe-virtio.bin",
690 a1e0fea5 Gerd Hoffmann
        .qdev.props = (Property[]) {
691 97b15621 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
692 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
693 97b15621 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
694 f0c07c7c Alex Williamson
            DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy,
695 f0c07c7c Alex Williamson
                               net.txtimer, TX_TIMER_INTERVAL),
696 e3f30488 Alex Williamson
            DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy,
697 e3f30488 Alex Williamson
                              net.txburst, TX_BURST),
698 a697a334 Alex Williamson
            DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
699 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
700 a1e0fea5 Gerd Hoffmann
        },
701 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
702 0aab0d3a Gerd Hoffmann
    },{
703 98b19252 Amit Shah
        .qdev.name = "virtio-serial-pci",
704 98b19252 Amit Shah
        .qdev.alias = "virtio-serial",
705 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
706 98b19252 Amit Shah
        .init      = virtio_serial_init_pci,
707 8b53a865 Amit Shah
        .exit      = virtio_serial_exit_pci,
708 d6beee99 Gerd Hoffmann
        .qdev.props = (Property[]) {
709 573fb60c Amit Shah
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
710 573fb60c Amit Shah
                               DEV_NVECTORS_UNSPECIFIED),
711 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
712 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
713 98b19252 Amit Shah
            DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
714 98b19252 Amit Shah
                               31),
715 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
716 d6beee99 Gerd Hoffmann
        },
717 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
718 0aab0d3a Gerd Hoffmann
    },{
719 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-balloon-pci",
720 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
721 0aab0d3a Gerd Hoffmann
        .init      = virtio_balloon_init_pci,
722 0f457d91 Michael S. Tsirkin
        .exit      = virtio_exit_pci,
723 8172539d Michael S. Tsirkin
        .qdev.props = (Property[]) {
724 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
725 8172539d Michael S. Tsirkin
            DEFINE_PROP_END_OF_LIST(),
726 8172539d Michael S. Tsirkin
        },
727 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
728 0aab0d3a Gerd Hoffmann
    },{
729 758e8e38 Venkateswararao Jujjuri (JV)
#ifdef CONFIG_VIRTFS
730 9f107513 Anthony Liguori
        .qdev.name = "virtio-9p-pci",
731 9f107513 Anthony Liguori
        .qdev.size = sizeof(VirtIOPCIProxy),
732 9f107513 Anthony Liguori
        .init      = virtio_9p_init_pci,
733 9f107513 Anthony Liguori
        .qdev.props = (Property[]) {
734 9f107513 Anthony Liguori
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
735 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
736 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
737 9f107513 Anthony Liguori
            DEFINE_PROP_END_OF_LIST(),
738 9f107513 Anthony Liguori
        },
739 9f107513 Anthony Liguori
    }, {
740 9f107513 Anthony Liguori
#endif
741 0aab0d3a Gerd Hoffmann
        /* end of list */
742 0aab0d3a Gerd Hoffmann
    }
743 0aab0d3a Gerd Hoffmann
};
744 0aab0d3a Gerd Hoffmann
745 53c25cea Paul Brook
static void virtio_pci_register_devices(void)
746 53c25cea Paul Brook
{
747 0aab0d3a Gerd Hoffmann
    pci_qdev_register_many(virtio_info);
748 53c25cea Paul Brook
}
749 53c25cea Paul Brook
750 53c25cea Paul Brook
device_init(virtio_pci_register_devices)