diff options
Diffstat (limited to 'hw/virtio/virtio-pci.c')
-rw-r--r-- | hw/virtio/virtio-pci.c | 852 |
1 files changed, 89 insertions, 763 deletions
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index a954799267..b282109343 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -19,12 +19,6 @@ #include "standard-headers/linux/virtio_pci.h" #include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-blk.h" -#include "hw/virtio/virtio-net.h" -#include "hw/virtio/virtio-serial.h" -#include "hw/virtio/virtio-scsi.h" -#include "hw/virtio/virtio-balloon.h" -#include "hw/virtio/virtio-input.h" #include "hw/pci/pci.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -1079,55 +1073,6 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running) } } -#ifdef CONFIG_VIRTFS -static void virtio_9p_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - V9fsPCIState *dev = VIRTIO_9P_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static Property virtio_9p_pci_properties[] = { - DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, - VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_9p_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - - k->realize = virtio_9p_pci_realize; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_9P; - pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; - pcidev_k->class_id = 0x2; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->props = virtio_9p_pci_properties; -} - -static void virtio_9p_pci_instance_init(Object *obj) -{ - V9fsPCIState *dev = VIRTIO_9P_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_9P); -} - -static const TypeInfo virtio_9p_pci_info = { - .name = TYPE_VIRTIO_9P_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(V9fsPCIState), - .instance_init = virtio_9p_pci_instance_init, - .class_init = virtio_9p_pci_class_init, -}; -#endif /* CONFIG_VIRTFS */ - /* * virtio-pci: This is the PCIDevice which has a virtio-pci-bus. */ @@ -1877,9 +1822,6 @@ static void virtio_pci_reset(DeviceState *qdev) static Property virtio_pci_properties[] = { DEFINE_PROP_BIT("virtio-pci-bus-master-bug-migration", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, false), - DEFINE_PROP_ON_OFF_AUTO("disable-legacy", VirtIOPCIProxy, disable_legacy, - ON_OFF_AUTO_AUTO), - DEFINE_PROP_BOOL("disable-modern", VirtIOPCIProxy, disable_modern, false), DEFINE_PROP_BIT("migrate-extra", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT, true), DEFINE_PROP_BIT("modern-pio-notify", VirtIOPCIProxy, flags, @@ -1939,712 +1881,123 @@ static const TypeInfo virtio_pci_info = { .class_init = virtio_pci_class_init, .class_size = sizeof(VirtioPCIClass), .abstract = true, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_PCIE_DEVICE }, - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { } - }, -}; - -/* virtio-blk-pci */ - -static Property virtio_blk_pci_properties[] = { - DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), - DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, - VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, - DEV_NVECTORS_UNSPECIFIED), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - - if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = dev->vdev.conf.num_queues + 1; - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void virtio_blk_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->props = virtio_blk_pci_properties; - k->realize = virtio_blk_pci_realize; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK; - pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; - pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; -} - -static void virtio_blk_pci_instance_init(Object *obj) -{ - VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_BLK); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); -} - -static const TypeInfo virtio_blk_pci_info = { - .name = TYPE_VIRTIO_BLK_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIOBlkPCI), - .instance_init = virtio_blk_pci_instance_init, - .class_init = virtio_blk_pci_class_init, -}; - -#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) -/* vhost-user-blk */ - -static Property vhost_user_blk_pci_properties[] = { - DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, - DEV_NVECTORS_UNSPECIFIED), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vhost_user_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VHostUserBlkPCI *dev = VHOST_USER_BLK_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - - if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = dev->vdev.num_queues + 1; - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void vhost_user_blk_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->props = vhost_user_blk_pci_properties; - k->realize = vhost_user_blk_pci_realize; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK; - pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; - pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; -} - -static void vhost_user_blk_pci_instance_init(Object *obj) -{ - VHostUserBlkPCI *dev = VHOST_USER_BLK_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VHOST_USER_BLK); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); -} - -static const TypeInfo vhost_user_blk_pci_info = { - .name = TYPE_VHOST_USER_BLK_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VHostUserBlkPCI), - .instance_init = vhost_user_blk_pci_instance_init, - .class_init = vhost_user_blk_pci_class_init, -}; -#endif - -/* virtio-scsi-pci */ - -static Property virtio_scsi_pci_properties[] = { - DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, - VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, - DEV_NVECTORS_UNSPECIFIED), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); - DeviceState *proxy = DEVICE(vpci_dev); - char *bus_name; - - if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = vs->conf.num_queues + 3; - } - - /* - * For command line compatibility, this sets the virtio-scsi-device bus - * name as before. - */ - if (proxy->id) { - bus_name = g_strdup_printf("%s.0", proxy->id); - virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); - g_free(bus_name); - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - k->realize = virtio_scsi_pci_realize; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->props = virtio_scsi_pci_properties; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; - pcidev_k->revision = 0x00; - pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; -} - -static void virtio_scsi_pci_instance_init(Object *obj) -{ - VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_SCSI); -} - -static const TypeInfo virtio_scsi_pci_info = { - .name = TYPE_VIRTIO_SCSI_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIOSCSIPCI), - .instance_init = virtio_scsi_pci_instance_init, - .class_init = virtio_scsi_pci_class_init, -}; - -/* vhost-scsi-pci */ - -#ifdef CONFIG_VHOST_SCSI -static Property vhost_scsi_pci_properties[] = { - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, - DEV_NVECTORS_UNSPECIFIED), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vhost_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VHostSCSIPCI *dev = VHOST_SCSI_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); - - if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = vs->conf.num_queues + 3; - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - k->realize = vhost_scsi_pci_realize; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->props = vhost_scsi_pci_properties; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; - pcidev_k->revision = 0x00; - pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; -} - -static void vhost_scsi_pci_instance_init(Object *obj) -{ - VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VHOST_SCSI); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); -} - -static const TypeInfo vhost_scsi_pci_info = { - .name = TYPE_VHOST_SCSI_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VHostSCSIPCI), - .instance_init = vhost_scsi_pci_instance_init, - .class_init = vhost_scsi_pci_class_init, -}; -#endif - -#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) -/* vhost-user-scsi-pci */ -static Property vhost_user_scsi_pci_properties[] = { - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, - DEV_NVECTORS_UNSPECIFIED), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vhost_user_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VHostUserSCSIPCI *dev = VHOST_USER_SCSI_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); - - if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = vs->conf.num_queues + 3; - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void vhost_user_scsi_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - k->realize = vhost_user_scsi_pci_realize; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->props = vhost_user_scsi_pci_properties; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; - pcidev_k->revision = 0x00; - pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI; -} - -static void vhost_user_scsi_pci_instance_init(Object *obj) -{ - VHostUserSCSIPCI *dev = VHOST_USER_SCSI_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VHOST_USER_SCSI); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); -} - -static const TypeInfo vhost_user_scsi_pci_info = { - .name = TYPE_VHOST_USER_SCSI_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VHostUserSCSIPCI), - .instance_init = vhost_user_scsi_pci_instance_init, - .class_init = vhost_user_scsi_pci_class_init, -}; -#endif - -/* vhost-vsock-pci */ - -#ifdef CONFIG_VHOST_VSOCK -static Property vhost_vsock_pci_properties[] = { - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), - DEFINE_PROP_END_OF_LIST(), }; -static void vhost_vsock_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VHostVSockPCI *dev = VHOST_VSOCK_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void vhost_vsock_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - k->realize = vhost_vsock_pci_realize; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - dc->props = vhost_vsock_pci_properties; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_VSOCK; - pcidev_k->revision = 0x00; - pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; -} - -static void vhost_vsock_pci_instance_init(Object *obj) -{ - VHostVSockPCI *dev = VHOST_VSOCK_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VHOST_VSOCK); -} - -static const TypeInfo vhost_vsock_pci_info = { - .name = TYPE_VHOST_VSOCK_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VHostVSockPCI), - .instance_init = vhost_vsock_pci_instance_init, - .class_init = vhost_vsock_pci_class_init, -}; -#endif - -/* virtio-balloon-pci */ - -static Property virtio_balloon_pci_properties[] = { - DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), +static Property virtio_pci_generic_properties[] = { + DEFINE_PROP_ON_OFF_AUTO("disable-legacy", VirtIOPCIProxy, disable_legacy, + ON_OFF_AUTO_AUTO), + DEFINE_PROP_BOOL("disable-modern", VirtIOPCIProxy, disable_modern, false), DEFINE_PROP_END_OF_LIST(), }; -static void virtio_balloon_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - - if (vpci_dev->class_code != PCI_CLASS_OTHERS && - vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */ - vpci_dev->class_code = PCI_CLASS_OTHERS; - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - k->realize = virtio_balloon_pci_realize; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - dc->props = virtio_balloon_pci_properties; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON; - pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; - pcidev_k->class_id = PCI_CLASS_OTHERS; -} - -static void virtio_balloon_pci_instance_init(Object *obj) -{ - VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_BALLOON); - object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev), - "guest-stats", &error_abort); - object_property_add_alias(obj, "guest-stats-polling-interval", - OBJECT(&dev->vdev), - "guest-stats-polling-interval", &error_abort); -} - -static const TypeInfo virtio_balloon_pci_info = { - .name = TYPE_VIRTIO_BALLOON_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIOBalloonPCI), - .instance_init = virtio_balloon_pci_instance_init, - .class_init = virtio_balloon_pci_class_init, -}; - -/* virtio-serial-pci */ - -static void virtio_serial_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +static void virtio_pci_base_class_init(ObjectClass *klass, void *data) { - VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - DeviceState *proxy = DEVICE(vpci_dev); - char *bus_name; - - if (vpci_dev->class_code != PCI_CLASS_COMMUNICATION_OTHER && - vpci_dev->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */ - vpci_dev->class_code != PCI_CLASS_OTHERS) { /* qemu-kvm */ - vpci_dev->class_code = PCI_CLASS_COMMUNICATION_OTHER; - } - - /* backwards-compatibility with machines that were created with - DEV_NVECTORS_UNSPECIFIED */ - if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { - vpci_dev->nvectors = dev->vdev.serial.max_virtserial_ports + 1; + const VirtioPCIDeviceTypeInfo *t = data; + if (t->class_init) { + t->class_init(klass, NULL); } - - /* - * For command line compatibility, this sets the virtio-serial-device bus - * name as before. - */ - if (proxy->id) { - bus_name = g_strdup_printf("%s.0", proxy->id); - virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); - g_free(bus_name); - } - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); } -static Property virtio_serial_pci_properties[] = { - DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, - VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), - DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_serial_pci_class_init(ObjectClass *klass, void *data) +static void virtio_pci_generic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - k->realize = virtio_serial_pci_realize; - set_bit(DEVICE_CATEGORY_INPUT, dc->categories); - dc->props = virtio_serial_pci_properties; - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE; - pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; - pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; -} -static void virtio_serial_pci_instance_init(Object *obj) -{ - VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_SERIAL); + dc->props = virtio_pci_generic_properties; } -static const TypeInfo virtio_serial_pci_info = { - .name = TYPE_VIRTIO_SERIAL_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIOSerialPCI), - .instance_init = virtio_serial_pci_instance_init, - .class_init = virtio_serial_pci_class_init, -}; - -/* virtio-net-pci */ - -static Property virtio_net_properties[] = { - DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, - VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +/* Used when the generic type and the base type is the same */ +static void virtio_pci_generic_base_class_init(ObjectClass *klass, void *data) { - DeviceState *qdev = DEVICE(vpci_dev); - VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - - virtio_net_set_netclient_name(&dev->vdev, qdev->id, - object_get_typename(OBJECT(qdev))); - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); + virtio_pci_base_class_init(klass, data); + virtio_pci_generic_class_init(klass, NULL); } -static void virtio_net_pci_class_init(ObjectClass *klass, void *data) +static void virtio_pci_transitional_instance_init(Object *obj) { - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass); + VirtIOPCIProxy *proxy = VIRTIO_PCI(obj); - k->romfile = "efi-virtio.rom"; - k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - k->device_id = PCI_DEVICE_ID_VIRTIO_NET; - k->revision = VIRTIO_PCI_ABI_VERSION; - k->class_id = PCI_CLASS_NETWORK_ETHERNET; - set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); - dc->props = virtio_net_properties; - vpciklass->realize = virtio_net_pci_realize; + proxy->disable_legacy = ON_OFF_AUTO_OFF; + proxy->disable_modern = false; } -static void virtio_net_pci_instance_init(Object *obj) +static void virtio_pci_non_transitional_instance_init(Object *obj) { - VirtIONetPCI *dev = VIRTIO_NET_PCI(obj); + VirtIOPCIProxy *proxy = VIRTIO_PCI(obj); - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_NET); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); + proxy->disable_legacy = ON_OFF_AUTO_ON; + proxy->disable_modern = false; } -static const TypeInfo virtio_net_pci_info = { - .name = TYPE_VIRTIO_NET_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIONetPCI), - .instance_init = virtio_net_pci_instance_init, - .class_init = virtio_net_pci_class_init, -}; - -/* virtio-rng-pci */ - -static void virtio_rng_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t) { - VirtIORngPCI *vrng = VIRTIO_RNG_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&vrng->vdev); - Error *err = NULL; + TypeInfo base_type_info = { + .name = t->base_name, + .parent = t->parent ? t->parent : TYPE_VIRTIO_PCI, + .instance_size = t->instance_size, + .instance_init = t->instance_init, + .class_init = virtio_pci_base_class_init, + .class_data = (void *)t, + .abstract = true, + }; + TypeInfo generic_type_info = { + .name = t->generic_name, + .parent = base_type_info.name, + .class_init = virtio_pci_generic_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_PCIE_DEVICE }, + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { } + }, + }; - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; + if (!base_type_info.name) { + /* No base type -> register a single generic device type */ + base_type_info.name = t->generic_name; + base_type_info.class_init = virtio_pci_generic_base_class_init; + base_type_info.interfaces = generic_type_info.interfaces; + base_type_info.abstract = false; + generic_type_info.name = NULL; + assert(!t->non_transitional_name); + assert(!t->transitional_name); + } + + type_register(&base_type_info); + if (generic_type_info.name) { + type_register(&generic_type_info); + } + + if (t->non_transitional_name) { + const TypeInfo non_transitional_type_info = { + .name = t->non_transitional_name, + .parent = base_type_info.name, + .instance_init = virtio_pci_non_transitional_instance_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_PCIE_DEVICE }, + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { } + }, + }; + type_register(&non_transitional_type_info); + } + + if (t->transitional_name) { + const TypeInfo transitional_type_info = { + .name = t->transitional_name, + .parent = base_type_info.name, + .instance_init = virtio_pci_transitional_instance_init, + .interfaces = (InterfaceInfo[]) { + /* + * Transitional virtio devices work only as Conventional PCI + * devices because they require PIO ports. + */ + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { } + }, + }; + type_register(&transitional_type_info); } - - object_property_set_link(OBJECT(vrng), - OBJECT(vrng->vdev.conf.rng), "rng", - NULL); } -static void virtio_rng_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - k->realize = virtio_rng_pci_realize; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - - pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; - pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_RNG; - pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; - pcidev_k->class_id = PCI_CLASS_OTHERS; -} - -static void virtio_rng_initfn(Object *obj) -{ - VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_RNG); -} - -static const TypeInfo virtio_rng_pci_info = { - .name = TYPE_VIRTIO_RNG_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIORngPCI), - .instance_init = virtio_rng_initfn, - .class_init = virtio_rng_pci_class_init, -}; - -/* virtio-input-pci */ - -static Property virtio_input_pci_properties[] = { - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), - DEFINE_PROP_END_OF_LIST(), -}; - -static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) -{ - VirtIOInputPCI *vinput = VIRTIO_INPUT_PCI(vpci_dev); - DeviceState *vdev = DEVICE(&vinput->vdev); - - qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - virtio_pci_force_virtio_1(vpci_dev); - object_property_set_bool(OBJECT(vdev), true, "realized", errp); -} - -static void virtio_input_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - dc->props = virtio_input_pci_properties; - k->realize = virtio_input_pci_realize; - set_bit(DEVICE_CATEGORY_INPUT, dc->categories); - - pcidev_k->class_id = PCI_CLASS_INPUT_OTHER; -} - -static void virtio_input_hid_kbd_pci_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - pcidev_k->class_id = PCI_CLASS_INPUT_KEYBOARD; -} - -static void virtio_input_hid_mouse_pci_class_init(ObjectClass *klass, - void *data) -{ - PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); - - pcidev_k->class_id = PCI_CLASS_INPUT_MOUSE; -} - -static void virtio_keyboard_initfn(Object *obj) -{ - VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_KEYBOARD); -} - -static void virtio_mouse_initfn(Object *obj) -{ - VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_MOUSE); -} - -static void virtio_tablet_initfn(Object *obj) -{ - VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_TABLET); -} - -static const TypeInfo virtio_input_pci_info = { - .name = TYPE_VIRTIO_INPUT_PCI, - .parent = TYPE_VIRTIO_PCI, - .instance_size = sizeof(VirtIOInputPCI), - .class_init = virtio_input_pci_class_init, - .abstract = true, -}; - -static const TypeInfo virtio_input_hid_pci_info = { - .name = TYPE_VIRTIO_INPUT_HID_PCI, - .parent = TYPE_VIRTIO_INPUT_PCI, - .instance_size = sizeof(VirtIOInputHIDPCI), - .abstract = true, -}; - -static const TypeInfo virtio_keyboard_pci_info = { - .name = TYPE_VIRTIO_KEYBOARD_PCI, - .parent = TYPE_VIRTIO_INPUT_HID_PCI, - .class_init = virtio_input_hid_kbd_pci_class_init, - .instance_size = sizeof(VirtIOInputHIDPCI), - .instance_init = virtio_keyboard_initfn, -}; - -static const TypeInfo virtio_mouse_pci_info = { - .name = TYPE_VIRTIO_MOUSE_PCI, - .parent = TYPE_VIRTIO_INPUT_HID_PCI, - .class_init = virtio_input_hid_mouse_pci_class_init, - .instance_size = sizeof(VirtIOInputHIDPCI), - .instance_init = virtio_mouse_initfn, -}; - -static const TypeInfo virtio_tablet_pci_info = { - .name = TYPE_VIRTIO_TABLET_PCI, - .parent = TYPE_VIRTIO_INPUT_HID_PCI, - .instance_size = sizeof(VirtIOInputHIDPCI), - .instance_init = virtio_tablet_initfn, -}; - -#ifdef CONFIG_LINUX -static void virtio_host_initfn(Object *obj) -{ - VirtIOInputHostPCI *dev = VIRTIO_INPUT_HOST_PCI(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_INPUT_HOST); -} - -static const TypeInfo virtio_host_pci_info = { - .name = TYPE_VIRTIO_INPUT_HOST_PCI, - .parent = TYPE_VIRTIO_INPUT_PCI, - .instance_size = sizeof(VirtIOInputHostPCI), - .instance_init = virtio_host_initfn, -}; -#endif - /* virtio-pci-bus */ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, @@ -2692,37 +2045,10 @@ static const TypeInfo virtio_pci_bus_info = { static void virtio_pci_register_types(void) { - type_register_static(&virtio_rng_pci_info); - type_register_static(&virtio_input_pci_info); - type_register_static(&virtio_input_hid_pci_info); - type_register_static(&virtio_keyboard_pci_info); - type_register_static(&virtio_mouse_pci_info); - type_register_static(&virtio_tablet_pci_info); -#ifdef CONFIG_LINUX - type_register_static(&virtio_host_pci_info); -#endif + /* Base types: */ type_register_static(&virtio_pci_bus_info); type_register_static(&virtio_pci_info); -#ifdef CONFIG_VIRTFS - type_register_static(&virtio_9p_pci_info); -#endif - type_register_static(&virtio_blk_pci_info); -#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) - type_register_static(&vhost_user_blk_pci_info); -#endif - type_register_static(&virtio_scsi_pci_info); - type_register_static(&virtio_balloon_pci_info); - type_register_static(&virtio_serial_pci_info); - type_register_static(&virtio_net_pci_info); -#ifdef CONFIG_VHOST_SCSI - type_register_static(&vhost_scsi_pci_info); -#endif -#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) - type_register_static(&vhost_user_scsi_pci_info); -#endif -#ifdef CONFIG_VHOST_VSOCK - type_register_static(&vhost_vsock_pci_info); -#endif } type_init(virtio_pci_register_types) + |