Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ 9dbcca5a

History | View | Annotate | Download (24.3 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 54dd9321 Michael S. Tsirkin
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
455 54dd9321 Michael S. Tsirkin
{
456 54dd9321 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
457 54dd9321 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
458 54dd9321 Michael S. Tsirkin
    int r, n;
459 54dd9321 Michael S. Tsirkin
460 54dd9321 Michael S. Tsirkin
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
461 54dd9321 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, n)) {
462 54dd9321 Michael S. Tsirkin
            break;
463 54dd9321 Michael S. Tsirkin
        }
464 54dd9321 Michael S. Tsirkin
465 54dd9321 Michael S. Tsirkin
        r = virtio_pci_set_guest_notifier(opaque, n, assign);
466 54dd9321 Michael S. Tsirkin
        if (r < 0) {
467 54dd9321 Michael S. Tsirkin
            goto assign_error;
468 54dd9321 Michael S. Tsirkin
        }
469 54dd9321 Michael S. Tsirkin
    }
470 54dd9321 Michael S. Tsirkin
471 54dd9321 Michael S. Tsirkin
    return 0;
472 54dd9321 Michael S. Tsirkin
473 54dd9321 Michael S. Tsirkin
assign_error:
474 54dd9321 Michael S. Tsirkin
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
475 54dd9321 Michael S. Tsirkin
    while (--n >= 0) {
476 54dd9321 Michael S. Tsirkin
        virtio_pci_set_guest_notifier(opaque, n, !assign);
477 54dd9321 Michael S. Tsirkin
    }
478 54dd9321 Michael S. Tsirkin
    return r;
479 54dd9321 Michael S. Tsirkin
}
480 54dd9321 Michael S. Tsirkin
481 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
482 ade80dc8 Michael S. Tsirkin
{
483 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
484 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
485 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
486 ade80dc8 Michael S. Tsirkin
    int r;
487 ade80dc8 Michael S. Tsirkin
    if (assign) {
488 ade80dc8 Michael S. Tsirkin
        r = event_notifier_init(notifier, 1);
489 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
490 ade80dc8 Michael S. Tsirkin
            return r;
491 ade80dc8 Michael S. Tsirkin
        }
492 ade80dc8 Michael S. Tsirkin
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
493 ade80dc8 Michael S. Tsirkin
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
494 ade80dc8 Michael S. Tsirkin
                                       n, assign);
495 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
496 ade80dc8 Michael S. Tsirkin
            event_notifier_cleanup(notifier);
497 ade80dc8 Michael S. Tsirkin
        }
498 ade80dc8 Michael S. Tsirkin
    } else {
499 ade80dc8 Michael S. Tsirkin
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
500 ade80dc8 Michael S. Tsirkin
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
501 ade80dc8 Michael S. Tsirkin
                                       n, assign);
502 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
503 ade80dc8 Michael S. Tsirkin
            return r;
504 ade80dc8 Michael S. Tsirkin
        }
505 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
506 ade80dc8 Michael S. Tsirkin
    }
507 ade80dc8 Michael S. Tsirkin
    return r;
508 ade80dc8 Michael S. Tsirkin
}
509 ade80dc8 Michael S. Tsirkin
510 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
511 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
512 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
513 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
514 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
515 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
516 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
517 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
518 54dd9321 Michael S. Tsirkin
    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
519 53c25cea Paul Brook
};
520 53c25cea Paul Brook
521 53c25cea Paul Brook
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
522 53c25cea Paul Brook
                            uint16_t vendor, uint16_t device,
523 53c25cea Paul Brook
                            uint16_t class_code, uint8_t pif)
524 53c25cea Paul Brook
{
525 53c25cea Paul Brook
    uint8_t *config;
526 53c25cea Paul Brook
    uint32_t size;
527 53c25cea Paul Brook
528 53c25cea Paul Brook
    proxy->vdev = vdev;
529 53c25cea Paul Brook
530 53c25cea Paul Brook
    config = proxy->pci_dev.config;
531 53c25cea Paul Brook
    pci_config_set_vendor_id(config, vendor);
532 53c25cea Paul Brook
    pci_config_set_device_id(config, device);
533 53c25cea Paul Brook
534 53c25cea Paul Brook
    config[0x08] = VIRTIO_PCI_ABI_VERSION;
535 53c25cea Paul Brook
536 53c25cea Paul Brook
    config[0x09] = pif;
537 53c25cea Paul Brook
    pci_config_set_class(config, class_code);
538 53c25cea Paul Brook
539 53c25cea Paul Brook
    config[0x2c] = vendor & 0xFF;
540 53c25cea Paul Brook
    config[0x2d] = (vendor >> 8) & 0xFF;
541 53c25cea Paul Brook
    config[0x2e] = vdev->device_id & 0xFF;
542 53c25cea Paul Brook
    config[0x2f] = (vdev->device_id >> 8) & 0xFF;
543 53c25cea Paul Brook
544 53c25cea Paul Brook
    config[0x3d] = 1;
545 53c25cea Paul Brook
546 5a1fc5e8 Michael S. Tsirkin
    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
547 aba800a3 Michael S. Tsirkin
        pci_register_bar(&proxy->pci_dev, 1,
548 aba800a3 Michael S. Tsirkin
                         msix_bar_size(&proxy->pci_dev),
549 0392a017 Isaku Yamahata
                         PCI_BASE_ADDRESS_SPACE_MEMORY,
550 aba800a3 Michael S. Tsirkin
                         msix_mmio_map);
551 aba800a3 Michael S. Tsirkin
    } else
552 aba800a3 Michael S. Tsirkin
        vdev->nvectors = 0;
553 aba800a3 Michael S. Tsirkin
554 ed757e14 Yan Vugenfirer
    proxy->pci_dev.config_write = virtio_write_config;
555 ed757e14 Yan Vugenfirer
556 aba800a3 Michael S. Tsirkin
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
557 53c25cea Paul Brook
    if (size & (size-1))
558 53c25cea Paul Brook
        size = 1 << qemu_fls(size);
559 53c25cea Paul Brook
560 0392a017 Isaku Yamahata
    pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
561 53c25cea Paul Brook
                           virtio_map);
562 53c25cea Paul Brook
563 53c25cea Paul Brook
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
564 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
565 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
566 8172539d Michael S. Tsirkin
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
567 53c25cea Paul Brook
}
568 53c25cea Paul Brook
569 81a322d4 Gerd Hoffmann
static int virtio_blk_init_pci(PCIDevice *pci_dev)
570 53c25cea Paul Brook
{
571 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
572 53c25cea Paul Brook
    VirtIODevice *vdev;
573 53c25cea Paul Brook
574 ab73ff29 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
575 ab73ff29 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
576 ab73ff29 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
577 53c25cea Paul Brook
578 428c149b Christoph Hellwig
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
579 ac0c14d7 Markus Armbruster
    if (!vdev) {
580 ac0c14d7 Markus Armbruster
        return -1;
581 ac0c14d7 Markus Armbruster
    }
582 177539e0 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
583 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
584 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
585 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_BLOCK,
586 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
587 177539e0 Gerd Hoffmann
    /* make the actual value visible */
588 177539e0 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
589 81a322d4 Gerd Hoffmann
    return 0;
590 21d58b57 Mark McLoughlin
}
591 21d58b57 Mark McLoughlin
592 0f457d91 Michael S. Tsirkin
static int virtio_exit_pci(PCIDevice *pci_dev)
593 0f457d91 Michael S. Tsirkin
{
594 0f457d91 Michael S. Tsirkin
    return msix_uninit(pci_dev);
595 0f457d91 Michael S. Tsirkin
}
596 0f457d91 Michael S. Tsirkin
597 56a14938 Gerd Hoffmann
static int virtio_blk_exit_pci(PCIDevice *pci_dev)
598 56a14938 Gerd Hoffmann
{
599 56a14938 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
600 56a14938 Gerd Hoffmann
601 9d0d3138 Alex Williamson
    virtio_blk_exit(proxy->vdev);
602 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(proxy->block.bs);
603 0f457d91 Michael S. Tsirkin
    return virtio_exit_pci(pci_dev);
604 56a14938 Gerd Hoffmann
}
605 56a14938 Gerd Hoffmann
606 98b19252 Amit Shah
static int virtio_serial_init_pci(PCIDevice *pci_dev)
607 21d58b57 Mark McLoughlin
{
608 d6beee99 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
609 85c2c735 Mark McLoughlin
    VirtIODevice *vdev;
610 85c2c735 Mark McLoughlin
611 d6beee99 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
612 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
613 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
614 d6beee99 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
615 d6beee99 Gerd Hoffmann
616 98b19252 Amit Shah
    vdev = virtio_serial_init(&pci_dev->qdev, proxy->max_virtserial_ports);
617 25fe3654 Amit Shah
    if (!vdev) {
618 25fe3654 Amit Shah
        return -1;
619 25fe3654 Amit Shah
    }
620 573fb60c Amit Shah
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
621 573fb60c Amit Shah
                                        ? proxy->max_virtserial_ports + 1
622 573fb60c Amit Shah
                                        : proxy->nvectors;
623 85c2c735 Mark McLoughlin
    virtio_init_pci(proxy, vdev,
624 85c2c735 Mark McLoughlin
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
625 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_CONSOLE,
626 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
627 a1829205 Amit Shah
    proxy->nvectors = vdev->nvectors;
628 81a322d4 Gerd Hoffmann
    return 0;
629 53c25cea Paul Brook
}
630 53c25cea Paul Brook
631 8b53a865 Amit Shah
static int virtio_serial_exit_pci(PCIDevice *pci_dev)
632 8b53a865 Amit Shah
{
633 8b53a865 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
634 8b53a865 Amit Shah
635 8b53a865 Amit Shah
    virtio_serial_exit(proxy->vdev);
636 8b53a865 Amit Shah
    return virtio_exit_pci(pci_dev);
637 8b53a865 Amit Shah
}
638 8b53a865 Amit Shah
639 81a322d4 Gerd Hoffmann
static int virtio_net_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 f0c07c7c Alex Williamson
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
645 a1e0fea5 Gerd Hoffmann
646 97b15621 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
647 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
648 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
649 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_NET,
650 53c25cea Paul Brook
                    PCI_CLASS_NETWORK_ETHERNET,
651 53c25cea Paul Brook
                    0x00);
652 a1e0fea5 Gerd Hoffmann
653 a1e0fea5 Gerd Hoffmann
    /* make the actual value visible */
654 a1e0fea5 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
655 81a322d4 Gerd Hoffmann
    return 0;
656 53c25cea Paul Brook
}
657 53c25cea Paul Brook
658 97b15621 Gerd Hoffmann
static int virtio_net_exit_pci(PCIDevice *pci_dev)
659 97b15621 Gerd Hoffmann
{
660 97b15621 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
661 97b15621 Gerd Hoffmann
662 97b15621 Gerd Hoffmann
    virtio_net_exit(proxy->vdev);
663 97b15621 Gerd Hoffmann
    return virtio_exit_pci(pci_dev);
664 97b15621 Gerd Hoffmann
}
665 97b15621 Gerd Hoffmann
666 81a322d4 Gerd Hoffmann
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
667 53c25cea Paul Brook
{
668 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
669 53c25cea Paul Brook
    VirtIODevice *vdev;
670 53c25cea Paul Brook
671 53c25cea Paul Brook
    vdev = virtio_balloon_init(&pci_dev->qdev);
672 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
673 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
674 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_BALLOON,
675 53c25cea Paul Brook
                    PCI_CLASS_MEMORY_RAM,
676 53c25cea Paul Brook
                    0x00);
677 81a322d4 Gerd Hoffmann
    return 0;
678 53c25cea Paul Brook
}
679 53c25cea Paul Brook
680 758e8e38 Venkateswararao Jujjuri (JV)
#ifdef CONFIG_VIRTFS
681 9f107513 Anthony Liguori
static int virtio_9p_init_pci(PCIDevice *pci_dev)
682 9f107513 Anthony Liguori
{
683 9f107513 Anthony Liguori
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
684 9f107513 Anthony Liguori
    VirtIODevice *vdev;
685 9f107513 Anthony Liguori
686 9f107513 Anthony Liguori
    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
687 9dbcca5a Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
688 9f107513 Anthony Liguori
    virtio_init_pci(proxy, vdev,
689 9f107513 Anthony Liguori
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
690 9f107513 Anthony Liguori
                    0x1009,
691 9f107513 Anthony Liguori
                    0x2,
692 9f107513 Anthony Liguori
                    0x00);
693 9dbcca5a Gerd Hoffmann
    /* make the actual value visible */
694 9dbcca5a Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
695 9f107513 Anthony Liguori
    return 0;
696 9f107513 Anthony Liguori
}
697 9f107513 Anthony Liguori
#endif
698 9f107513 Anthony Liguori
699 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo virtio_info[] = {
700 0aab0d3a Gerd Hoffmann
    {
701 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-blk-pci",
702 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
703 0aab0d3a Gerd Hoffmann
        .init      = virtio_blk_init_pci,
704 56a14938 Gerd Hoffmann
        .exit      = virtio_blk_exit_pci,
705 ab73ff29 Gerd Hoffmann
        .qdev.props = (Property[]) {
706 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
707 428c149b Christoph Hellwig
            DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
708 177539e0 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
709 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
710 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
711 ab73ff29 Gerd Hoffmann
        },
712 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
713 0aab0d3a Gerd Hoffmann
    },{
714 a1e0fea5 Gerd Hoffmann
        .qdev.name  = "virtio-net-pci",
715 a1e0fea5 Gerd Hoffmann
        .qdev.size  = sizeof(VirtIOPCIProxy),
716 a1e0fea5 Gerd Hoffmann
        .init       = virtio_net_init_pci,
717 97b15621 Gerd Hoffmann
        .exit       = virtio_net_exit_pci,
718 8c52c8f3 Gerd Hoffmann
        .romfile    = "pxe-virtio.bin",
719 a1e0fea5 Gerd Hoffmann
        .qdev.props = (Property[]) {
720 97b15621 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
721 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
722 97b15621 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
723 f0c07c7c Alex Williamson
            DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy,
724 f0c07c7c Alex Williamson
                               net.txtimer, TX_TIMER_INTERVAL),
725 e3f30488 Alex Williamson
            DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy,
726 e3f30488 Alex Williamson
                              net.txburst, TX_BURST),
727 a697a334 Alex Williamson
            DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
728 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
729 a1e0fea5 Gerd Hoffmann
        },
730 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
731 0aab0d3a Gerd Hoffmann
    },{
732 98b19252 Amit Shah
        .qdev.name = "virtio-serial-pci",
733 98b19252 Amit Shah
        .qdev.alias = "virtio-serial",
734 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
735 98b19252 Amit Shah
        .init      = virtio_serial_init_pci,
736 8b53a865 Amit Shah
        .exit      = virtio_serial_exit_pci,
737 d6beee99 Gerd Hoffmann
        .qdev.props = (Property[]) {
738 573fb60c Amit Shah
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
739 573fb60c Amit Shah
                               DEV_NVECTORS_UNSPECIFIED),
740 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
741 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
742 98b19252 Amit Shah
            DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
743 98b19252 Amit Shah
                               31),
744 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
745 d6beee99 Gerd Hoffmann
        },
746 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
747 0aab0d3a Gerd Hoffmann
    },{
748 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-balloon-pci",
749 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
750 0aab0d3a Gerd Hoffmann
        .init      = virtio_balloon_init_pci,
751 0f457d91 Michael S. Tsirkin
        .exit      = virtio_exit_pci,
752 8172539d Michael S. Tsirkin
        .qdev.props = (Property[]) {
753 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
754 8172539d Michael S. Tsirkin
            DEFINE_PROP_END_OF_LIST(),
755 8172539d Michael S. Tsirkin
        },
756 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
757 0aab0d3a Gerd Hoffmann
    },{
758 758e8e38 Venkateswararao Jujjuri (JV)
#ifdef CONFIG_VIRTFS
759 9f107513 Anthony Liguori
        .qdev.name = "virtio-9p-pci",
760 9f107513 Anthony Liguori
        .qdev.size = sizeof(VirtIOPCIProxy),
761 9f107513 Anthony Liguori
        .init      = virtio_9p_init_pci,
762 9f107513 Anthony Liguori
        .qdev.props = (Property[]) {
763 9dbcca5a Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
764 9f107513 Anthony Liguori
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
765 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
766 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
767 9f107513 Anthony Liguori
            DEFINE_PROP_END_OF_LIST(),
768 9f107513 Anthony Liguori
        },
769 9f107513 Anthony Liguori
    }, {
770 9f107513 Anthony Liguori
#endif
771 0aab0d3a Gerd Hoffmann
        /* end of list */
772 0aab0d3a Gerd Hoffmann
    }
773 0aab0d3a Gerd Hoffmann
};
774 0aab0d3a Gerd Hoffmann
775 53c25cea Paul Brook
static void virtio_pci_register_devices(void)
776 53c25cea Paul Brook
{
777 0aab0d3a Gerd Hoffmann
    pci_qdev_register_many(virtio_info);
778 53c25cea Paul Brook
}
779 53c25cea Paul Brook
780 53c25cea Paul Brook
device_init(virtio_pci_register_devices)