]> Git Repo - qemu.git/blob - hw/virtio-pci.c
Sparc32: remove dead increment, spotted by clang
[qemu.git] / hw / virtio-pci.c
1 /*
2  * Virtio PCI Bindings
3  *
4  * Copyright IBM, Corp. 2007
5  * Copyright (c) 2009 CodeSourcery
6  *
7  * Authors:
8  *  Anthony Liguori   <[email protected]>
9  *  Paul Brook        <[email protected]>
10  *
11  * This work is licensed under the terms of the GNU GPL, version 2.  See
12  * the COPYING file in the top-level directory.
13  *
14  */
15
16 #include <inttypes.h>
17
18 #include "virtio.h"
19 #include "virtio-blk.h"
20 #include "virtio-net.h"
21 #include "pci.h"
22 #include "sysemu.h"
23 #include "msix.h"
24 #include "net.h"
25 #include "loader.h"
26
27 /* from Linux's linux/virtio_pci.h */
28
29 /* A 32-bit r/o bitmask of the features supported by the host */
30 #define VIRTIO_PCI_HOST_FEATURES        0
31
32 /* A 32-bit r/w bitmask of features activated by the guest */
33 #define VIRTIO_PCI_GUEST_FEATURES       4
34
35 /* A 32-bit r/w PFN for the currently selected queue */
36 #define VIRTIO_PCI_QUEUE_PFN            8
37
38 /* A 16-bit r/o queue size for the currently selected queue */
39 #define VIRTIO_PCI_QUEUE_NUM            12
40
41 /* A 16-bit r/w queue selector */
42 #define VIRTIO_PCI_QUEUE_SEL            14
43
44 /* A 16-bit r/w queue notifier */
45 #define VIRTIO_PCI_QUEUE_NOTIFY         16
46
47 /* An 8-bit device status register.  */
48 #define VIRTIO_PCI_STATUS               18
49
50 /* An 8-bit r/o interrupt status register.  Reading the value will return the
51  * current contents of the ISR and will also clear it.  This is effectively
52  * a read-and-acknowledge. */
53 #define VIRTIO_PCI_ISR                  19
54
55 /* MSI-X registers: only enabled if MSI-X is enabled. */
56 /* A 16-bit vector for configuration changes. */
57 #define VIRTIO_MSI_CONFIG_VECTOR        20
58 /* A 16-bit vector for selected queue notifications. */
59 #define VIRTIO_MSI_QUEUE_VECTOR         22
60
61 /* Config space size */
62 #define VIRTIO_PCI_CONFIG_NOMSI         20
63 #define VIRTIO_PCI_CONFIG_MSI           24
64 #define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
65                                          VIRTIO_PCI_CONFIG_MSI : \
66                                          VIRTIO_PCI_CONFIG_NOMSI)
67
68 /* The remaining space is defined by each driver as the per-driver
69  * configuration space */
70 #define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
71                                          VIRTIO_PCI_CONFIG_MSI : \
72                                          VIRTIO_PCI_CONFIG_NOMSI)
73
74 /* Virtio ABI version, if we increment this, we break the guest driver. */
75 #define VIRTIO_PCI_ABI_VERSION          0
76
77 /* How many bits to shift physical queue address written to QUEUE_PFN.
78  * 12 is historical, and due to x86 page size. */
79 #define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
80
81 /* QEMU doesn't strictly need write barriers since everything runs in
82  * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
83  * KVM or if kqemu gets SMP support.
84  */
85 #define wmb() do { } while (0)
86
87 /* PCI bindings.  */
88
89 typedef struct {
90     PCIDevice pci_dev;
91     VirtIODevice *vdev;
92     uint32_t addr;
93     uint32_t class_code;
94     uint32_t nvectors;
95     DriveInfo *dinfo;
96     NICConf nic;
97     uint32_t host_features;
98 } VirtIOPCIProxy;
99
100 /* virtio device */
101
102 static void virtio_pci_notify(void *opaque, uint16_t vector)
103 {
104     VirtIOPCIProxy *proxy = opaque;
105     if (msix_enabled(&proxy->pci_dev))
106         msix_notify(&proxy->pci_dev, vector);
107     else
108         qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
109 }
110
111 static void virtio_pci_save_config(void * opaque, QEMUFile *f)
112 {
113     VirtIOPCIProxy *proxy = opaque;
114     pci_device_save(&proxy->pci_dev, f);
115     msix_save(&proxy->pci_dev, f);
116     if (msix_present(&proxy->pci_dev))
117         qemu_put_be16(f, proxy->vdev->config_vector);
118 }
119
120 static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
121 {
122     VirtIOPCIProxy *proxy = opaque;
123     if (msix_present(&proxy->pci_dev))
124         qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
125 }
126
127 static int virtio_pci_load_config(void * opaque, QEMUFile *f)
128 {
129     VirtIOPCIProxy *proxy = opaque;
130     int ret;
131     ret = pci_device_load(&proxy->pci_dev, f);
132     if (ret) {
133         return ret;
134     }
135     msix_load(&proxy->pci_dev, f);
136     if (msix_present(&proxy->pci_dev)) {
137         qemu_get_be16s(f, &proxy->vdev->config_vector);
138     } else {
139         proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
140     }
141     if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
142         return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
143     }
144     return 0;
145 }
146
147 static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
148 {
149     VirtIOPCIProxy *proxy = opaque;
150     uint16_t vector;
151     if (msix_present(&proxy->pci_dev)) {
152         qemu_get_be16s(f, &vector);
153     } else {
154         vector = VIRTIO_NO_VECTOR;
155     }
156     virtio_queue_set_vector(proxy->vdev, n, vector);
157     if (vector != VIRTIO_NO_VECTOR) {
158         return msix_vector_use(&proxy->pci_dev, vector);
159     }
160     return 0;
161 }
162
163 static void virtio_pci_reset(DeviceState *d)
164 {
165     VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
166     virtio_reset(proxy->vdev);
167     msix_reset(&proxy->pci_dev);
168 }
169
170 static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
171 {
172     VirtIOPCIProxy *proxy = opaque;
173     VirtIODevice *vdev = proxy->vdev;
174     target_phys_addr_t pa;
175
176     switch (addr) {
177     case VIRTIO_PCI_GUEST_FEATURES:
178         /* Guest does not negotiate properly?  We have to assume nothing. */
179         if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
180             if (vdev->bad_features)
181                 val = proxy->host_features & vdev->bad_features(vdev);
182             else
183                 val = 0;
184         }
185         if (vdev->set_features)
186             vdev->set_features(vdev, val);
187         vdev->guest_features = val;
188         break;
189     case VIRTIO_PCI_QUEUE_PFN:
190         pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
191         if (pa == 0) {
192             virtio_reset(proxy->vdev);
193             msix_unuse_all_vectors(&proxy->pci_dev);
194         }
195         else
196             virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
197         break;
198     case VIRTIO_PCI_QUEUE_SEL:
199         if (val < VIRTIO_PCI_QUEUE_MAX)
200             vdev->queue_sel = val;
201         break;
202     case VIRTIO_PCI_QUEUE_NOTIFY:
203         virtio_queue_notify(vdev, val);
204         break;
205     case VIRTIO_PCI_STATUS:
206         vdev->status = val & 0xFF;
207         if (vdev->status == 0) {
208             virtio_reset(proxy->vdev);
209             msix_unuse_all_vectors(&proxy->pci_dev);
210         }
211         break;
212     case VIRTIO_MSI_CONFIG_VECTOR:
213         msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
214         /* Make it possible for guest to discover an error took place. */
215         if (msix_vector_use(&proxy->pci_dev, val) < 0)
216             val = VIRTIO_NO_VECTOR;
217         vdev->config_vector = val;
218         break;
219     case VIRTIO_MSI_QUEUE_VECTOR:
220         msix_vector_unuse(&proxy->pci_dev,
221                           virtio_queue_vector(vdev, vdev->queue_sel));
222         /* Make it possible for guest to discover an error took place. */
223         if (msix_vector_use(&proxy->pci_dev, val) < 0)
224             val = VIRTIO_NO_VECTOR;
225         virtio_queue_set_vector(vdev, vdev->queue_sel, val);
226         break;
227     default:
228         fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n",
229                 __func__, addr, val);
230         break;
231     }
232 }
233
234 static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
235 {
236     VirtIODevice *vdev = proxy->vdev;
237     uint32_t ret = 0xFFFFFFFF;
238
239     switch (addr) {
240     case VIRTIO_PCI_HOST_FEATURES:
241         ret = proxy->host_features;
242         break;
243     case VIRTIO_PCI_GUEST_FEATURES:
244         ret = vdev->guest_features;
245         break;
246     case VIRTIO_PCI_QUEUE_PFN:
247         ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
248               >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
249         break;
250     case VIRTIO_PCI_QUEUE_NUM:
251         ret = virtio_queue_get_num(vdev, vdev->queue_sel);
252         break;
253     case VIRTIO_PCI_QUEUE_SEL:
254         ret = vdev->queue_sel;
255         break;
256     case VIRTIO_PCI_STATUS:
257         ret = vdev->status;
258         break;
259     case VIRTIO_PCI_ISR:
260         /* reading from the ISR also clears it. */
261         ret = vdev->isr;
262         vdev->isr = 0;
263         qemu_set_irq(proxy->pci_dev.irq[0], 0);
264         break;
265     case VIRTIO_MSI_CONFIG_VECTOR:
266         ret = vdev->config_vector;
267         break;
268     case VIRTIO_MSI_QUEUE_VECTOR:
269         ret = virtio_queue_vector(vdev, vdev->queue_sel);
270         break;
271     default:
272         break;
273     }
274
275     return ret;
276 }
277
278 static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
279 {
280     VirtIOPCIProxy *proxy = opaque;
281     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
282     addr -= proxy->addr;
283     if (addr < config)
284         return virtio_ioport_read(proxy, addr);
285     addr -= config;
286     return virtio_config_readb(proxy->vdev, addr);
287 }
288
289 static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
290 {
291     VirtIOPCIProxy *proxy = opaque;
292     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
293     addr -= proxy->addr;
294     if (addr < config)
295         return virtio_ioport_read(proxy, addr);
296     addr -= config;
297     return virtio_config_readw(proxy->vdev, addr);
298 }
299
300 static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
301 {
302     VirtIOPCIProxy *proxy = opaque;
303     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
304     addr -= proxy->addr;
305     if (addr < config)
306         return virtio_ioport_read(proxy, addr);
307     addr -= config;
308     return virtio_config_readl(proxy->vdev, addr);
309 }
310
311 static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
312 {
313     VirtIOPCIProxy *proxy = opaque;
314     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
315     addr -= proxy->addr;
316     if (addr < config) {
317         virtio_ioport_write(proxy, addr, val);
318         return;
319     }
320     addr -= config;
321     virtio_config_writeb(proxy->vdev, addr, val);
322 }
323
324 static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
325 {
326     VirtIOPCIProxy *proxy = opaque;
327     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
328     addr -= proxy->addr;
329     if (addr < config) {
330         virtio_ioport_write(proxy, addr, val);
331         return;
332     }
333     addr -= config;
334     virtio_config_writew(proxy->vdev, addr, val);
335 }
336
337 static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
338 {
339     VirtIOPCIProxy *proxy = opaque;
340     uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
341     addr -= proxy->addr;
342     if (addr < config) {
343         virtio_ioport_write(proxy, addr, val);
344         return;
345     }
346     addr -= config;
347     virtio_config_writel(proxy->vdev, addr, val);
348 }
349
350 static void virtio_map(PCIDevice *pci_dev, int region_num,
351                        pcibus_t addr, pcibus_t size, int type)
352 {
353     VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
354     VirtIODevice *vdev = proxy->vdev;
355     unsigned config_len = VIRTIO_PCI_REGION_SIZE(pci_dev) + vdev->config_len;
356
357     proxy->addr = addr;
358
359     register_ioport_write(addr, config_len, 1, virtio_pci_config_writeb, proxy);
360     register_ioport_write(addr, config_len, 2, virtio_pci_config_writew, proxy);
361     register_ioport_write(addr, config_len, 4, virtio_pci_config_writel, proxy);
362     register_ioport_read(addr, config_len, 1, virtio_pci_config_readb, proxy);
363     register_ioport_read(addr, config_len, 2, virtio_pci_config_readw, proxy);
364     register_ioport_read(addr, config_len, 4, virtio_pci_config_readl, proxy);
365
366     if (vdev->config_len)
367         vdev->get_config(vdev, vdev->config);
368 }
369
370 static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
371                                 uint32_t val, int len)
372 {
373     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
374
375     if (PCI_COMMAND == address) {
376         if (!(val & PCI_COMMAND_MASTER)) {
377             proxy->vdev->status &= ~VIRTIO_CONFIG_S_DRIVER_OK;
378         }
379     }
380
381     pci_default_write_config(pci_dev, address, val, len);
382     msix_write_config(pci_dev, address, val, len);
383 }
384
385 static unsigned virtio_pci_get_features(void *opaque)
386 {
387     VirtIOPCIProxy *proxy = opaque;
388     return proxy->host_features;
389 }
390
391 static const VirtIOBindings virtio_pci_bindings = {
392     .notify = virtio_pci_notify,
393     .save_config = virtio_pci_save_config,
394     .load_config = virtio_pci_load_config,
395     .save_queue = virtio_pci_save_queue,
396     .load_queue = virtio_pci_load_queue,
397     .get_features = virtio_pci_get_features,
398 };
399
400 static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
401                             uint16_t vendor, uint16_t device,
402                             uint16_t class_code, uint8_t pif)
403 {
404     uint8_t *config;
405     uint32_t size;
406
407     proxy->vdev = vdev;
408
409     config = proxy->pci_dev.config;
410     pci_config_set_vendor_id(config, vendor);
411     pci_config_set_device_id(config, device);
412
413     config[0x08] = VIRTIO_PCI_ABI_VERSION;
414
415     config[0x09] = pif;
416     pci_config_set_class(config, class_code);
417     config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
418
419     config[0x2c] = vendor & 0xFF;
420     config[0x2d] = (vendor >> 8) & 0xFF;
421     config[0x2e] = vdev->device_id & 0xFF;
422     config[0x2f] = (vdev->device_id >> 8) & 0xFF;
423
424     config[0x3d] = 1;
425
426     if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
427         pci_register_bar(&proxy->pci_dev, 1,
428                          msix_bar_size(&proxy->pci_dev),
429                          PCI_BASE_ADDRESS_SPACE_MEMORY,
430                          msix_mmio_map);
431     } else
432         vdev->nvectors = 0;
433
434     proxy->pci_dev.config_write = virtio_write_config;
435
436     size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
437     if (size & (size-1))
438         size = 1 << qemu_fls(size);
439
440     pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
441                            virtio_map);
442
443     virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
444     proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
445     proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
446     proxy->host_features = vdev->get_features(vdev, proxy->host_features);
447 }
448
449 static int virtio_blk_init_pci(PCIDevice *pci_dev)
450 {
451     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
452     VirtIODevice *vdev;
453
454     if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
455         proxy->class_code != PCI_CLASS_STORAGE_OTHER)
456         proxy->class_code = PCI_CLASS_STORAGE_SCSI;
457
458     if (!proxy->dinfo) {
459         qemu_error("virtio-blk-pci: drive property not set\n");
460         return -1;
461     }
462     vdev = virtio_blk_init(&pci_dev->qdev, proxy->dinfo);
463     vdev->nvectors = proxy->nvectors;
464     virtio_init_pci(proxy, vdev,
465                     PCI_VENDOR_ID_REDHAT_QUMRANET,
466                     PCI_DEVICE_ID_VIRTIO_BLOCK,
467                     proxy->class_code, 0x00);
468     /* make the actual value visible */
469     proxy->nvectors = vdev->nvectors;
470     return 0;
471 }
472
473 static int virtio_exit_pci(PCIDevice *pci_dev)
474 {
475     return msix_uninit(pci_dev);
476 }
477
478 static int virtio_blk_exit_pci(PCIDevice *pci_dev)
479 {
480     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
481
482     drive_uninit(proxy->dinfo);
483     return virtio_exit_pci(pci_dev);
484 }
485
486 static int virtio_console_init_pci(PCIDevice *pci_dev)
487 {
488     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
489     VirtIODevice *vdev;
490
491     if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
492         proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
493         proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
494         proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
495
496     vdev = virtio_console_init(&pci_dev->qdev);
497     if (!vdev) {
498         return -1;
499     }
500     virtio_init_pci(proxy, vdev,
501                     PCI_VENDOR_ID_REDHAT_QUMRANET,
502                     PCI_DEVICE_ID_VIRTIO_CONSOLE,
503                     proxy->class_code, 0x00);
504     return 0;
505 }
506
507 static int virtio_net_init_pci(PCIDevice *pci_dev)
508 {
509     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
510     VirtIODevice *vdev;
511
512     vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic);
513
514     vdev->nvectors = proxy->nvectors;
515     virtio_init_pci(proxy, vdev,
516                     PCI_VENDOR_ID_REDHAT_QUMRANET,
517                     PCI_DEVICE_ID_VIRTIO_NET,
518                     PCI_CLASS_NETWORK_ETHERNET,
519                     0x00);
520
521     /* make the actual value visible */
522     proxy->nvectors = vdev->nvectors;
523     return 0;
524 }
525
526 static int virtio_net_exit_pci(PCIDevice *pci_dev)
527 {
528     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
529
530     virtio_net_exit(proxy->vdev);
531     return virtio_exit_pci(pci_dev);
532 }
533
534 static int virtio_balloon_init_pci(PCIDevice *pci_dev)
535 {
536     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
537     VirtIODevice *vdev;
538
539     vdev = virtio_balloon_init(&pci_dev->qdev);
540     virtio_init_pci(proxy, vdev,
541                     PCI_VENDOR_ID_REDHAT_QUMRANET,
542                     PCI_DEVICE_ID_VIRTIO_BALLOON,
543                     PCI_CLASS_MEMORY_RAM,
544                     0x00);
545     return 0;
546 }
547
548 static PCIDeviceInfo virtio_info[] = {
549     {
550         .qdev.name = "virtio-blk-pci",
551         .qdev.size = sizeof(VirtIOPCIProxy),
552         .init      = virtio_blk_init_pci,
553         .exit      = virtio_blk_exit_pci,
554         .qdev.props = (Property[]) {
555             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
556             DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo),
557             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
558             DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
559             DEFINE_PROP_END_OF_LIST(),
560         },
561         .qdev.reset = virtio_pci_reset,
562     },{
563         .qdev.name  = "virtio-net-pci",
564         .qdev.size  = sizeof(VirtIOPCIProxy),
565         .init       = virtio_net_init_pci,
566         .exit       = virtio_net_exit_pci,
567         .romfile    = "pxe-virtio.bin",
568         .qdev.props = (Property[]) {
569             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
570             DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
571             DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
572             DEFINE_PROP_END_OF_LIST(),
573         },
574         .qdev.reset = virtio_pci_reset,
575     },{
576         .qdev.name = "virtio-console-pci",
577         .qdev.size = sizeof(VirtIOPCIProxy),
578         .init      = virtio_console_init_pci,
579         .exit      = virtio_exit_pci,
580         .qdev.props = (Property[]) {
581             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
582             DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
583             DEFINE_PROP_END_OF_LIST(),
584         },
585         .qdev.reset = virtio_pci_reset,
586     },{
587         .qdev.name = "virtio-balloon-pci",
588         .qdev.size = sizeof(VirtIOPCIProxy),
589         .init      = virtio_balloon_init_pci,
590         .exit      = virtio_exit_pci,
591         .qdev.props = (Property[]) {
592             DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
593             DEFINE_PROP_END_OF_LIST(),
594         },
595         .qdev.reset = virtio_pci_reset,
596     },{
597         /* end of list */
598     }
599 };
600
601 static void virtio_pci_register_devices(void)
602 {
603     pci_qdev_register_many(virtio_info);
604 }
605
606 device_init(virtio_pci_register_devices)
This page took 0.058579 seconds and 4 git commands to generate.