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