Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ e075e788

History | View | Annotate | Download (23.1 kB)

1 53c25cea Paul Brook
/*
2 53c25cea Paul Brook
 * Virtio PCI Bindings
3 53c25cea Paul Brook
 *
4 53c25cea Paul Brook
 * Copyright IBM, Corp. 2007
5 53c25cea Paul Brook
 * Copyright (c) 2009 CodeSourcery
6 53c25cea Paul Brook
 *
7 53c25cea Paul Brook
 * Authors:
8 53c25cea Paul Brook
 *  Anthony Liguori   <aliguori@us.ibm.com>
9 53c25cea Paul Brook
 *  Paul Brook        <paul@codesourcery.com>
10 53c25cea Paul Brook
 *
11 53c25cea Paul Brook
 * This work is licensed under the terms of the GNU GPL, version 2.  See
12 53c25cea Paul Brook
 * the COPYING file in the top-level directory.
13 53c25cea Paul Brook
 *
14 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 428c149b Christoph Hellwig
#include "block_int.h"
26 97b15621 Gerd Hoffmann
#include "loader.h"
27 ade80dc8 Michael S. Tsirkin
#include "kvm.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 53c25cea Paul Brook
} VirtIOPCIProxy;
111 53c25cea Paul Brook
112 53c25cea Paul Brook
/* virtio device */
113 53c25cea Paul Brook
114 7055e687 Michael S. Tsirkin
static void virtio_pci_notify(void *opaque, uint16_t vector)
115 53c25cea Paul Brook
{
116 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
117 aba800a3 Michael S. Tsirkin
    if (msix_enabled(&proxy->pci_dev))
118 aba800a3 Michael S. Tsirkin
        msix_notify(&proxy->pci_dev, vector);
119 aba800a3 Michael S. Tsirkin
    else
120 aba800a3 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
121 53c25cea Paul Brook
}
122 53c25cea Paul Brook
123 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
124 ff24bd58 Michael S. Tsirkin
{
125 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
126 ff24bd58 Michael S. Tsirkin
    pci_device_save(&proxy->pci_dev, f);
127 ff24bd58 Michael S. Tsirkin
    msix_save(&proxy->pci_dev, f);
128 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
129 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, proxy->vdev->config_vector);
130 ff24bd58 Michael S. Tsirkin
}
131 ff24bd58 Michael S. Tsirkin
132 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
133 ff24bd58 Michael S. Tsirkin
{
134 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
135 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
136 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
137 ff24bd58 Michael S. Tsirkin
}
138 ff24bd58 Michael S. Tsirkin
139 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_config(void * opaque, QEMUFile *f)
140 ff24bd58 Michael S. Tsirkin
{
141 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
142 ff24bd58 Michael S. Tsirkin
    int ret;
143 ff24bd58 Michael S. Tsirkin
    ret = pci_device_load(&proxy->pci_dev, f);
144 e6da7680 Michael S. Tsirkin
    if (ret) {
145 ff24bd58 Michael S. Tsirkin
        return ret;
146 e6da7680 Michael S. Tsirkin
    }
147 ff24bd58 Michael S. Tsirkin
    msix_load(&proxy->pci_dev, f);
148 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
149 ff24bd58 Michael S. Tsirkin
        qemu_get_be16s(f, &proxy->vdev->config_vector);
150 e6da7680 Michael S. Tsirkin
    } else {
151 e6da7680 Michael S. Tsirkin
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
152 e6da7680 Michael S. Tsirkin
    }
153 e6da7680 Michael S. Tsirkin
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
154 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
155 e6da7680 Michael S. Tsirkin
    }
156 c81131db Alexander Graf
157 c81131db Alexander Graf
    /* Try to find out if the guest has bus master disabled, but is
158 c81131db Alexander Graf
       in ready state. Then we have a buggy guest OS. */
159 c81131db Alexander Graf
    if (!(proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
160 c81131db Alexander Graf
        !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
161 c81131db Alexander Graf
        proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
162 c81131db Alexander Graf
    }
163 ff24bd58 Michael S. Tsirkin
    return 0;
164 ff24bd58 Michael S. Tsirkin
}
165 ff24bd58 Michael S. Tsirkin
166 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
167 ff24bd58 Michael S. Tsirkin
{
168 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
169 ff24bd58 Michael S. Tsirkin
    uint16_t vector;
170 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
171 e6da7680 Michael S. Tsirkin
        qemu_get_be16s(f, &vector);
172 e6da7680 Michael S. Tsirkin
    } else {
173 e6da7680 Michael S. Tsirkin
        vector = VIRTIO_NO_VECTOR;
174 e6da7680 Michael S. Tsirkin
    }
175 ff24bd58 Michael S. Tsirkin
    virtio_queue_set_vector(proxy->vdev, n, vector);
176 e6da7680 Michael S. Tsirkin
    if (vector != VIRTIO_NO_VECTOR) {
177 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, vector);
178 e6da7680 Michael S. Tsirkin
    }
179 ff24bd58 Michael S. Tsirkin
    return 0;
180 ff24bd58 Michael S. Tsirkin
}
181 ff24bd58 Michael S. Tsirkin
182 e489030d Michael S. Tsirkin
static void virtio_pci_reset(DeviceState *d)
183 7055e687 Michael S. Tsirkin
{
184 e489030d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
185 7055e687 Michael S. Tsirkin
    virtio_reset(proxy->vdev);
186 aba800a3 Michael S. Tsirkin
    msix_reset(&proxy->pci_dev);
187 c81131db Alexander Graf
    proxy->bugs = 0;
188 7055e687 Michael S. Tsirkin
}
189 7055e687 Michael S. Tsirkin
190 53c25cea Paul Brook
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
191 53c25cea Paul Brook
{
192 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
193 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
194 c227f099 Anthony Liguori
    target_phys_addr_t pa;
195 53c25cea Paul Brook
196 53c25cea Paul Brook
    switch (addr) {
197 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
198 53c25cea Paul Brook
        /* Guest does not negotiate properly?  We have to assume nothing. */
199 53c25cea Paul Brook
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
200 53c25cea Paul Brook
            if (vdev->bad_features)
201 8172539d Michael S. Tsirkin
                val = proxy->host_features & vdev->bad_features(vdev);
202 53c25cea Paul Brook
            else
203 53c25cea Paul Brook
                val = 0;
204 53c25cea Paul Brook
        }
205 53c25cea Paul Brook
        if (vdev->set_features)
206 53c25cea Paul Brook
            vdev->set_features(vdev, val);
207 704a76fc Michael S. Tsirkin
        vdev->guest_features = val;
208 53c25cea Paul Brook
        break;
209 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
210 c227f099 Anthony Liguori
        pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
211 1b8e9b27 Michael S. Tsirkin
        if (pa == 0) {
212 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
213 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
214 1b8e9b27 Michael S. Tsirkin
        }
215 7055e687 Michael S. Tsirkin
        else
216 7055e687 Michael S. Tsirkin
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
217 53c25cea Paul Brook
        break;
218 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
219 53c25cea Paul Brook
        if (val < VIRTIO_PCI_QUEUE_MAX)
220 53c25cea Paul Brook
            vdev->queue_sel = val;
221 53c25cea Paul Brook
        break;
222 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NOTIFY:
223 53c25cea Paul Brook
        virtio_queue_notify(vdev, val);
224 53c25cea Paul Brook
        break;
225 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
226 3e607cb5 Michael S. Tsirkin
        virtio_set_status(vdev, val & 0xFF);
227 1b8e9b27 Michael S. Tsirkin
        if (vdev->status == 0) {
228 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
229 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
230 1b8e9b27 Michael S. Tsirkin
        }
231 c81131db Alexander Graf
232 c81131db Alexander Graf
        /* Linux before 2.6.34 sets the device as OK without enabling
233 c81131db Alexander Graf
           the PCI device bus master bit. In this case we need to disable
234 c81131db Alexander Graf
           some safety checks. */
235 c81131db Alexander Graf
        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
236 c81131db Alexander Graf
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
237 c81131db Alexander Graf
            proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
238 c81131db Alexander Graf
        }
239 53c25cea Paul Brook
        break;
240 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
241 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
242 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
243 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
244 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
245 aba800a3 Michael S. Tsirkin
        vdev->config_vector = val;
246 aba800a3 Michael S. Tsirkin
        break;
247 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
248 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev,
249 aba800a3 Michael S. Tsirkin
                          virtio_queue_vector(vdev, vdev->queue_sel));
250 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
251 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
252 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
253 aba800a3 Michael S. Tsirkin
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
254 aba800a3 Michael S. Tsirkin
        break;
255 aba800a3 Michael S. Tsirkin
    default:
256 aba800a3 Michael S. Tsirkin
        fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n",
257 aba800a3 Michael S. Tsirkin
                __func__, addr, val);
258 aba800a3 Michael S. Tsirkin
        break;
259 53c25cea Paul Brook
    }
260 53c25cea Paul Brook
}
261 53c25cea Paul Brook
262 aba800a3 Michael S. Tsirkin
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
263 53c25cea Paul Brook
{
264 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
265 53c25cea Paul Brook
    uint32_t ret = 0xFFFFFFFF;
266 53c25cea Paul Brook
267 53c25cea Paul Brook
    switch (addr) {
268 53c25cea Paul Brook
    case VIRTIO_PCI_HOST_FEATURES:
269 8172539d Michael S. Tsirkin
        ret = proxy->host_features;
270 53c25cea Paul Brook
        break;
271 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
272 704a76fc Michael S. Tsirkin
        ret = vdev->guest_features;
273 53c25cea Paul Brook
        break;
274 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
275 53c25cea Paul Brook
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
276 53c25cea Paul Brook
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
277 53c25cea Paul Brook
        break;
278 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NUM:
279 53c25cea Paul Brook
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
280 53c25cea Paul Brook
        break;
281 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
282 53c25cea Paul Brook
        ret = vdev->queue_sel;
283 53c25cea Paul Brook
        break;
284 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
285 53c25cea Paul Brook
        ret = vdev->status;
286 53c25cea Paul Brook
        break;
287 53c25cea Paul Brook
    case VIRTIO_PCI_ISR:
288 53c25cea Paul Brook
        /* reading from the ISR also clears it. */
289 53c25cea Paul Brook
        ret = vdev->isr;
290 53c25cea Paul Brook
        vdev->isr = 0;
291 7055e687 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
292 53c25cea Paul Brook
        break;
293 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
294 aba800a3 Michael S. Tsirkin
        ret = vdev->config_vector;
295 aba800a3 Michael S. Tsirkin
        break;
296 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
297 aba800a3 Michael S. Tsirkin
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
298 aba800a3 Michael S. Tsirkin
        break;
299 53c25cea Paul Brook
    default:
300 53c25cea Paul Brook
        break;
301 53c25cea Paul Brook
    }
302 53c25cea Paul Brook
303 53c25cea Paul Brook
    return ret;
304 53c25cea Paul Brook
}
305 53c25cea Paul Brook
306 53c25cea Paul Brook
static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
307 53c25cea Paul Brook
{
308 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
309 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
310 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
311 aba800a3 Michael S. Tsirkin
    if (addr < config)
312 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
313 aba800a3 Michael S. Tsirkin
    addr -= config;
314 53c25cea Paul Brook
    return virtio_config_readb(proxy->vdev, addr);
315 53c25cea Paul Brook
}
316 53c25cea Paul Brook
317 53c25cea Paul Brook
static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
318 53c25cea Paul Brook
{
319 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
320 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
321 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
322 aba800a3 Michael S. Tsirkin
    if (addr < config)
323 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
324 aba800a3 Michael S. Tsirkin
    addr -= config;
325 53c25cea Paul Brook
    return virtio_config_readw(proxy->vdev, addr);
326 53c25cea Paul Brook
}
327 53c25cea Paul Brook
328 53c25cea Paul Brook
static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
329 53c25cea Paul Brook
{
330 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
331 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
332 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
333 aba800a3 Michael S. Tsirkin
    if (addr < config)
334 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
335 aba800a3 Michael S. Tsirkin
    addr -= config;
336 53c25cea Paul Brook
    return virtio_config_readl(proxy->vdev, addr);
337 53c25cea Paul Brook
}
338 53c25cea Paul Brook
339 53c25cea Paul Brook
static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
340 53c25cea Paul Brook
{
341 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
342 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
343 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
344 aba800a3 Michael S. Tsirkin
    if (addr < config) {
345 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
346 aba800a3 Michael S. Tsirkin
        return;
347 aba800a3 Michael S. Tsirkin
    }
348 aba800a3 Michael S. Tsirkin
    addr -= config;
349 53c25cea Paul Brook
    virtio_config_writeb(proxy->vdev, addr, val);
350 53c25cea Paul Brook
}
351 53c25cea Paul Brook
352 53c25cea Paul Brook
static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
353 53c25cea Paul Brook
{
354 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
355 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
356 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
357 aba800a3 Michael S. Tsirkin
    if (addr < config) {
358 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
359 aba800a3 Michael S. Tsirkin
        return;
360 aba800a3 Michael S. Tsirkin
    }
361 aba800a3 Michael S. Tsirkin
    addr -= config;
362 53c25cea Paul Brook
    virtio_config_writew(proxy->vdev, addr, val);
363 53c25cea Paul Brook
}
364 53c25cea Paul Brook
365 53c25cea Paul Brook
static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
366 53c25cea Paul Brook
{
367 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
368 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
369 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
370 aba800a3 Michael S. Tsirkin
    if (addr < config) {
371 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
372 aba800a3 Michael S. Tsirkin
        return;
373 aba800a3 Michael S. Tsirkin
    }
374 aba800a3 Michael S. Tsirkin
    addr -= config;
375 53c25cea Paul Brook
    virtio_config_writel(proxy->vdev, addr, val);
376 53c25cea Paul Brook
}
377 53c25cea Paul Brook
378 53c25cea Paul Brook
static void virtio_map(PCIDevice *pci_dev, int region_num,
379 6e355d90 Isaku Yamahata
                       pcibus_t addr, pcibus_t size, int type)
380 53c25cea Paul Brook
{
381 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
382 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
383 aba800a3 Michael S. Tsirkin
    unsigned config_len = VIRTIO_PCI_REGION_SIZE(pci_dev) + vdev->config_len;
384 53c25cea Paul Brook
385 53c25cea Paul Brook
    proxy->addr = addr;
386 53c25cea Paul Brook
387 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 1, virtio_pci_config_writeb, proxy);
388 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 2, virtio_pci_config_writew, proxy);
389 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 4, virtio_pci_config_writel, proxy);
390 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 1, virtio_pci_config_readb, proxy);
391 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 2, virtio_pci_config_readw, proxy);
392 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 4, virtio_pci_config_readl, proxy);
393 53c25cea Paul Brook
394 aba800a3 Michael S. Tsirkin
    if (vdev->config_len)
395 53c25cea Paul Brook
        vdev->get_config(vdev, vdev->config);
396 aba800a3 Michael S. Tsirkin
}
397 aba800a3 Michael S. Tsirkin
398 aba800a3 Michael S. Tsirkin
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
399 aba800a3 Michael S. Tsirkin
                                uint32_t val, int len)
400 aba800a3 Michael S. Tsirkin
{
401 ed757e14 Yan Vugenfirer
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
402 ed757e14 Yan Vugenfirer
403 ed757e14 Yan Vugenfirer
    if (PCI_COMMAND == address) {
404 ed757e14 Yan Vugenfirer
        if (!(val & PCI_COMMAND_MASTER)) {
405 c81131db Alexander Graf
            if (!(proxy->bugs & VIRTIO_PCI_BUG_BUS_MASTER)) {
406 3e607cb5 Michael S. Tsirkin
                virtio_set_status(proxy->vdev,
407 3e607cb5 Michael S. Tsirkin
                                  proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
408 c81131db Alexander Graf
            }
409 ed757e14 Yan Vugenfirer
        }
410 ed757e14 Yan Vugenfirer
    }
411 ed757e14 Yan Vugenfirer
412 aba800a3 Michael S. Tsirkin
    pci_default_write_config(pci_dev, address, val, len);
413 85352471 Michael S. Tsirkin
    msix_write_config(pci_dev, address, val, len);
414 53c25cea Paul Brook
}
415 53c25cea Paul Brook
416 6d74ca5a Michael S. Tsirkin
static unsigned virtio_pci_get_features(void *opaque)
417 6d74ca5a Michael S. Tsirkin
{
418 8172539d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
419 8172539d Michael S. Tsirkin
    return proxy->host_features;
420 6d74ca5a Michael S. Tsirkin
}
421 6d74ca5a Michael S. Tsirkin
422 ade80dc8 Michael S. Tsirkin
static void virtio_pci_guest_notifier_read(void *opaque)
423 ade80dc8 Michael S. Tsirkin
{
424 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = opaque;
425 ade80dc8 Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
426 ade80dc8 Michael S. Tsirkin
    if (event_notifier_test_and_clear(n)) {
427 ade80dc8 Michael S. Tsirkin
        virtio_irq(vq);
428 ade80dc8 Michael S. Tsirkin
    }
429 ade80dc8 Michael S. Tsirkin
}
430 ade80dc8 Michael S. Tsirkin
431 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
432 ade80dc8 Michael S. Tsirkin
{
433 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
434 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
435 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
436 ade80dc8 Michael S. Tsirkin
437 ade80dc8 Michael S. Tsirkin
    if (assign) {
438 ade80dc8 Michael S. Tsirkin
        int r = event_notifier_init(notifier, 0);
439 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
440 ade80dc8 Michael S. Tsirkin
            return r;
441 ade80dc8 Michael S. Tsirkin
        }
442 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
443 ade80dc8 Michael S. Tsirkin
                            virtio_pci_guest_notifier_read, NULL, vq);
444 ade80dc8 Michael S. Tsirkin
    } else {
445 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
446 ade80dc8 Michael S. Tsirkin
                            NULL, NULL, NULL);
447 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
448 ade80dc8 Michael S. Tsirkin
    }
449 ade80dc8 Michael S. Tsirkin
450 ade80dc8 Michael S. Tsirkin
    return 0;
451 ade80dc8 Michael S. Tsirkin
}
452 ade80dc8 Michael S. Tsirkin
453 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
454 ade80dc8 Michael S. Tsirkin
{
455 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
456 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
457 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
458 ade80dc8 Michael S. Tsirkin
    int r;
459 ade80dc8 Michael S. Tsirkin
    if (assign) {
460 ade80dc8 Michael S. Tsirkin
        r = event_notifier_init(notifier, 1);
461 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
462 ade80dc8 Michael S. Tsirkin
            return r;
463 ade80dc8 Michael S. Tsirkin
        }
464 ade80dc8 Michael S. Tsirkin
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
465 ade80dc8 Michael S. Tsirkin
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
466 ade80dc8 Michael S. Tsirkin
                                       n, assign);
467 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
468 ade80dc8 Michael S. Tsirkin
            event_notifier_cleanup(notifier);
469 ade80dc8 Michael S. Tsirkin
        }
470 ade80dc8 Michael S. Tsirkin
    } else {
471 ade80dc8 Michael S. Tsirkin
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
472 ade80dc8 Michael S. Tsirkin
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
473 ade80dc8 Michael S. Tsirkin
                                       n, assign);
474 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
475 ade80dc8 Michael S. Tsirkin
            return r;
476 ade80dc8 Michael S. Tsirkin
        }
477 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
478 ade80dc8 Michael S. Tsirkin
    }
479 ade80dc8 Michael S. Tsirkin
    return r;
480 ade80dc8 Michael S. Tsirkin
}
481 ade80dc8 Michael S. Tsirkin
482 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
483 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
484 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
485 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
486 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
487 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
488 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
489 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
490 ade80dc8 Michael S. Tsirkin
    .set_guest_notifier = virtio_pci_set_guest_notifier,
491 53c25cea Paul Brook
};
492 53c25cea Paul Brook
493 53c25cea Paul Brook
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
494 53c25cea Paul Brook
                            uint16_t vendor, uint16_t device,
495 53c25cea Paul Brook
                            uint16_t class_code, uint8_t pif)
496 53c25cea Paul Brook
{
497 53c25cea Paul Brook
    uint8_t *config;
498 53c25cea Paul Brook
    uint32_t size;
499 53c25cea Paul Brook
500 53c25cea Paul Brook
    proxy->vdev = vdev;
501 53c25cea Paul Brook
502 53c25cea Paul Brook
    config = proxy->pci_dev.config;
503 53c25cea Paul Brook
    pci_config_set_vendor_id(config, vendor);
504 53c25cea Paul Brook
    pci_config_set_device_id(config, device);
505 53c25cea Paul Brook
506 53c25cea Paul Brook
    config[0x08] = VIRTIO_PCI_ABI_VERSION;
507 53c25cea Paul Brook
508 53c25cea Paul Brook
    config[0x09] = pif;
509 53c25cea Paul Brook
    pci_config_set_class(config, class_code);
510 53c25cea Paul Brook
    config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
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
    if (!proxy->block.dinfo) {
552 1ecda02b Markus Armbruster
        error_report("virtio-blk-pci: drive property not set");
553 81a322d4 Gerd Hoffmann
        return -1;
554 d176c495 Gerd Hoffmann
    }
555 428c149b Christoph Hellwig
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
556 177539e0 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
557 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
558 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
559 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_BLOCK,
560 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
561 177539e0 Gerd Hoffmann
    /* make the actual value visible */
562 177539e0 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
563 81a322d4 Gerd Hoffmann
    return 0;
564 21d58b57 Mark McLoughlin
}
565 21d58b57 Mark McLoughlin
566 0f457d91 Michael S. Tsirkin
static int virtio_exit_pci(PCIDevice *pci_dev)
567 0f457d91 Michael S. Tsirkin
{
568 0f457d91 Michael S. Tsirkin
    return msix_uninit(pci_dev);
569 0f457d91 Michael S. Tsirkin
}
570 0f457d91 Michael S. Tsirkin
571 56a14938 Gerd Hoffmann
static int virtio_blk_exit_pci(PCIDevice *pci_dev)
572 56a14938 Gerd Hoffmann
{
573 56a14938 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
574 56a14938 Gerd Hoffmann
575 428c149b Christoph Hellwig
    drive_uninit(proxy->block.dinfo);
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 81a322d4 Gerd Hoffmann
static int virtio_net_init_pci(PCIDevice *pci_dev)
605 53c25cea Paul Brook
{
606 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
607 53c25cea Paul Brook
    VirtIODevice *vdev;
608 53c25cea Paul Brook
609 97b15621 Gerd Hoffmann
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic);
610 a1e0fea5 Gerd Hoffmann
611 97b15621 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
612 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
613 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
614 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_NET,
615 53c25cea Paul Brook
                    PCI_CLASS_NETWORK_ETHERNET,
616 53c25cea Paul Brook
                    0x00);
617 a1e0fea5 Gerd Hoffmann
618 a1e0fea5 Gerd Hoffmann
    /* make the actual value visible */
619 a1e0fea5 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
620 81a322d4 Gerd Hoffmann
    return 0;
621 53c25cea Paul Brook
}
622 53c25cea Paul Brook
623 97b15621 Gerd Hoffmann
static int virtio_net_exit_pci(PCIDevice *pci_dev)
624 97b15621 Gerd Hoffmann
{
625 97b15621 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
626 97b15621 Gerd Hoffmann
627 97b15621 Gerd Hoffmann
    virtio_net_exit(proxy->vdev);
628 97b15621 Gerd Hoffmann
    return virtio_exit_pci(pci_dev);
629 97b15621 Gerd Hoffmann
}
630 97b15621 Gerd Hoffmann
631 81a322d4 Gerd Hoffmann
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
632 53c25cea Paul Brook
{
633 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
634 53c25cea Paul Brook
    VirtIODevice *vdev;
635 53c25cea Paul Brook
636 53c25cea Paul Brook
    vdev = virtio_balloon_init(&pci_dev->qdev);
637 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
638 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
639 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_BALLOON,
640 53c25cea Paul Brook
                    PCI_CLASS_MEMORY_RAM,
641 53c25cea Paul Brook
                    0x00);
642 81a322d4 Gerd Hoffmann
    return 0;
643 53c25cea Paul Brook
}
644 53c25cea Paul Brook
645 9f107513 Anthony Liguori
#ifdef CONFIG_LINUX
646 9f107513 Anthony Liguori
static int virtio_9p_init_pci(PCIDevice *pci_dev)
647 9f107513 Anthony Liguori
{
648 9f107513 Anthony Liguori
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
649 9f107513 Anthony Liguori
    VirtIODevice *vdev;
650 9f107513 Anthony Liguori
651 9f107513 Anthony Liguori
    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
652 9f107513 Anthony Liguori
    virtio_init_pci(proxy, vdev,
653 9f107513 Anthony Liguori
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
654 9f107513 Anthony Liguori
                    0x1009,
655 9f107513 Anthony Liguori
                    0x2,
656 9f107513 Anthony Liguori
                    0x00);
657 9f107513 Anthony Liguori
658 9f107513 Anthony Liguori
    return 0;
659 9f107513 Anthony Liguori
}
660 9f107513 Anthony Liguori
#endif
661 9f107513 Anthony Liguori
662 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo virtio_info[] = {
663 0aab0d3a Gerd Hoffmann
    {
664 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-blk-pci",
665 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
666 0aab0d3a Gerd Hoffmann
        .init      = virtio_blk_init_pci,
667 56a14938 Gerd Hoffmann
        .exit      = virtio_blk_exit_pci,
668 ab73ff29 Gerd Hoffmann
        .qdev.props = (Property[]) {
669 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
670 428c149b Christoph Hellwig
            DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
671 177539e0 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
672 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
673 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
674 ab73ff29 Gerd Hoffmann
        },
675 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
676 0aab0d3a Gerd Hoffmann
    },{
677 a1e0fea5 Gerd Hoffmann
        .qdev.name  = "virtio-net-pci",
678 a1e0fea5 Gerd Hoffmann
        .qdev.size  = sizeof(VirtIOPCIProxy),
679 a1e0fea5 Gerd Hoffmann
        .init       = virtio_net_init_pci,
680 97b15621 Gerd Hoffmann
        .exit       = virtio_net_exit_pci,
681 8c52c8f3 Gerd Hoffmann
        .romfile    = "pxe-virtio.bin",
682 a1e0fea5 Gerd Hoffmann
        .qdev.props = (Property[]) {
683 97b15621 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
684 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
685 97b15621 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
686 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
687 a1e0fea5 Gerd Hoffmann
        },
688 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
689 0aab0d3a Gerd Hoffmann
    },{
690 98b19252 Amit Shah
        .qdev.name = "virtio-serial-pci",
691 98b19252 Amit Shah
        .qdev.alias = "virtio-serial",
692 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
693 98b19252 Amit Shah
        .init      = virtio_serial_init_pci,
694 0f457d91 Michael S. Tsirkin
        .exit      = virtio_exit_pci,
695 d6beee99 Gerd Hoffmann
        .qdev.props = (Property[]) {
696 573fb60c Amit Shah
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
697 573fb60c Amit Shah
                               DEV_NVECTORS_UNSPECIFIED),
698 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
699 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
700 98b19252 Amit Shah
            DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
701 98b19252 Amit Shah
                               31),
702 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
703 d6beee99 Gerd Hoffmann
        },
704 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
705 0aab0d3a Gerd Hoffmann
    },{
706 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-balloon-pci",
707 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
708 0aab0d3a Gerd Hoffmann
        .init      = virtio_balloon_init_pci,
709 0f457d91 Michael S. Tsirkin
        .exit      = virtio_exit_pci,
710 8172539d Michael S. Tsirkin
        .qdev.props = (Property[]) {
711 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
712 8172539d Michael S. Tsirkin
            DEFINE_PROP_END_OF_LIST(),
713 8172539d Michael S. Tsirkin
        },
714 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
715 0aab0d3a Gerd Hoffmann
    },{
716 9f107513 Anthony Liguori
#ifdef CONFIG_LINUX
717 9f107513 Anthony Liguori
        .qdev.name = "virtio-9p-pci",
718 9f107513 Anthony Liguori
        .qdev.size = sizeof(VirtIOPCIProxy),
719 9f107513 Anthony Liguori
        .init      = virtio_9p_init_pci,
720 9f107513 Anthony Liguori
        .qdev.props = (Property[]) {
721 9f107513 Anthony Liguori
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
722 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
723 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
724 9f107513 Anthony Liguori
            DEFINE_PROP_END_OF_LIST(),
725 9f107513 Anthony Liguori
        },
726 9f107513 Anthony Liguori
    }, {
727 9f107513 Anthony Liguori
#endif
728 0aab0d3a Gerd Hoffmann
        /* end of list */
729 0aab0d3a Gerd Hoffmann
    }
730 0aab0d3a Gerd Hoffmann
};
731 0aab0d3a Gerd Hoffmann
732 53c25cea Paul Brook
static void virtio_pci_register_devices(void)
733 53c25cea Paul Brook
{
734 0aab0d3a Gerd Hoffmann
    pci_qdev_register_many(virtio_info);
735 53c25cea Paul Brook
}
736 53c25cea Paul Brook
737 53c25cea Paul Brook
device_init(virtio_pci_register_devices)