From: Gerd Hoffmann <kra...@redhat.com> Initialize the modern bar and the VirtIOPCIRegion fields early, in realize. Also add a size field to VirtIOPCIRegion and variables for pci bars to VirtIOPCIProxy.
This allows virtio-pci subclasses to change things before the device_plugged callback applies them. virtio-vga will use that to arrange regions in a way that virtio-vga is compatible to both stdvga (in vga mode) and virtio-gpu-pci (in pci mode). Signed-off-by: Gerd Hoffmann <kra...@redhat.com> Reviewed-by: Michael S. Tsirkin <m...@redhat.com> Signed-off-by: Michael S. Tsirkin <m...@redhat.com> --- hw/virtio/virtio-pci.h | 4 +++ hw/virtio/virtio-pci.c | 92 ++++++++++++++++++++++++++++---------------------- 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index ea1343d..ff5ab71 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -94,6 +94,7 @@ typedef struct VirtioPCIClass { typedef struct VirtIOPCIRegion { MemoryRegion mr; uint32_t offset; + uint32_t size; uint32_t type; } VirtIOPCIRegion; @@ -105,6 +106,9 @@ struct VirtIOPCIProxy { VirtIOPCIRegion device; VirtIOPCIRegion notify; MemoryRegion modern_bar; + uint32_t legacy_io_bar; + uint32_t msix_bar; + uint32_t modern_mem_bar; uint32_t flags; uint32_t class_code; uint32_t nvectors; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 771bbd5..76653a7 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1250,32 +1250,26 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) memory_region_init_io(&proxy->common.mr, OBJECT(proxy), &common_ops, proxy, - "virtio-pci-common", 0x1000); - proxy->common.offset = 0x0; - proxy->common.type = VIRTIO_PCI_CAP_COMMON_CFG; + "virtio-pci-common", + proxy->common.size); memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), &isr_ops, proxy, - "virtio-pci-isr", 0x1000); - proxy->isr.offset = 0x1000; - proxy->isr.type = VIRTIO_PCI_CAP_ISR_CFG; + "virtio-pci-isr", + proxy->isr.size); memory_region_init_io(&proxy->device.mr, OBJECT(proxy), &device_ops, virtio_bus_get_device(&proxy->bus), - "virtio-pci-device", 0x1000); - proxy->device.offset = 0x2000; - proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG; + "virtio-pci-device", + proxy->device.size); memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), ¬ify_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-notify", - QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX); - proxy->notify.offset = 0x3000; - proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG; + proxy->notify.size); } static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, @@ -1287,8 +1281,9 @@ static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, ®ion->mr); cap->cfg_type = region->type; + cap->bar = proxy->modern_mem_bar; cap->offset = cpu_to_le32(region->offset); - cap->length = cpu_to_le32(memory_region_size(®ion->mr)); + cap->length = cpu_to_le32(region->size); virtio_pci_add_mem_cap(proxy, cap); } @@ -1303,22 +1298,6 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) uint32_t size; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - /* - * virtio pci bar layout - * - * region 0 -- virtio legacy io bar - * region 1 -- msi-x bar - * region 2+3 -- not used by virtio-pci - * region 4+5 -- virtio modern memory (64bit) bar - * - * Regions 2+3 can be used by VirtIOPCIProxy subclasses. - * virtio-vga places the vga framebuffer there. - * - */ - uint32_t legacy_io_bar = 0; - uint32_t msix_bar = 1; - uint32_t modern_mem_bar = 4; - config = proxy->pci_dev.config; if (proxy->class_code) { pci_config_set_class(config, proxy->class_code); @@ -1343,11 +1322,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (modern) { struct virtio_pci_cap cap = { .cap_len = sizeof cap, - .bar = modern_mem_bar, }; struct virtio_pci_notify_cap notify = { .cap.cap_len = sizeof notify, - .cap.bar = modern_mem_bar, .notify_off_multiplier = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT), }; @@ -1355,15 +1332,12 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) /* TODO: add io access for speed */ virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); - memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", - 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX); virtio_pci_modern_regions_init(proxy); virtio_pci_modern_region_map(proxy, &proxy->common, &cap); virtio_pci_modern_region_map(proxy, &proxy->isr, &cap); virtio_pci_modern_region_map(proxy, &proxy->device, &cap); virtio_pci_modern_region_map(proxy, &proxy->notify, ¬ify.cap); - pci_register_bar(&proxy->pci_dev, modern_mem_bar, + pci_register_bar(&proxy->pci_dev, proxy->modern_mem_bar, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH | PCI_BASE_ADDRESS_MEM_TYPE_64, @@ -1371,7 +1345,8 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) } if (proxy->nvectors && - msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, msix_bar)) { + msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, + proxy->msix_bar)) { error_report("unable to init msix vectors to %" PRIu32, proxy->nvectors); proxy->nvectors = 0; @@ -1390,7 +1365,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) &virtio_pci_config_ops, proxy, "virtio-pci", size); - pci_register_bar(&proxy->pci_dev, legacy_io_bar, + pci_register_bar(&proxy->pci_dev, proxy->legacy_io_bar, PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); } @@ -1410,12 +1385,47 @@ static void virtio_pci_device_unplugged(DeviceState *d) static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) { - VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev); + VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev); VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev); - virtio_pci_bus_new(&dev->bus, sizeof(dev->bus), dev); + /* + * virtio pci bar layout used by default. + * subclasses can re-arrange things if needed. + * + * region 0 -- virtio legacy io bar + * region 1 -- msi-x bar + * region 4+5 -- virtio modern memory (64bit) bar + * + */ + proxy->legacy_io_bar = 0; + proxy->msix_bar = 1; + proxy->modern_mem_bar = 4; + + proxy->common.offset = 0x0; + proxy->common.size = 0x1000; + proxy->common.type = VIRTIO_PCI_CAP_COMMON_CFG; + + proxy->isr.offset = 0x1000; + proxy->isr.size = 0x1000; + proxy->isr.type = VIRTIO_PCI_CAP_ISR_CFG; + + proxy->device.offset = 0x2000; + proxy->device.size = 0x1000; + proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG; + + proxy->notify.offset = 0x3000; + proxy->notify.size = + QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX; + proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG; + + /* subclasses can enforce modern, so do this unconditionally */ + memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", + 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + VIRTIO_QUEUE_MAX); + + virtio_pci_bus_new(&proxy->bus, sizeof(proxy->bus), proxy); if (k->realize) { - k->realize(dev, errp); + k->realize(proxy, errp); } } -- MST