Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ cc9577cf

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