@@ -201,10 +201,10 @@ static const MemoryRegionOps pci_vga_qext_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static void pci_std_vga_mmio_region_init(VGACommonState *s,
- MemoryRegion *parent,
- MemoryRegion *subs,
- bool qext)
+void pci_std_vga_mmio_region_init(VGACommonState *s,
+ MemoryRegion *parent,
+ MemoryRegion *subs,
+ bool qext)
{
memory_region_init_io(&subs[0], NULL, &pci_vga_ioport_ops, s,
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
@@ -221,4 +221,10 @@ extern const uint8_t gr_mask[16];
extern const MemoryRegionOps vga_mem_ops;
+/* vga-pci.c */
+void pci_std_vga_mmio_region_init(VGACommonState *s,
+ MemoryRegion *parent,
+ MemoryRegion *subs,
+ bool qext);
+
#endif
@@ -15,6 +15,7 @@ typedef struct VirtIOVGA {
VirtIOPCIProxy parent_obj;
VirtIOGPU vdev;
VGACommonState vga;
+ MemoryRegion vga_mrs[3];
uint32_t dummy;
} VirtIOVGA;
@@ -78,15 +79,28 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev);
VirtIOGPU *g = &vvga->vdev;
VGACommonState *vga = &vvga->vga;
+ uint32_t offset;
/* init vga compat bits */
vga->vram_size_mb = 8;
vga_common_init(vga, OBJECT(vpci_dev), false);
vga_init(vga, OBJECT(vpci_dev), pci_address_space(&vpci_dev->pci_dev),
pci_address_space_io(&vpci_dev->pci_dev), true);
- pci_register_bar(&vpci_dev->pci_dev, 2,
+ pci_register_bar(&vpci_dev->pci_dev, 0,
PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
+ /* configure virtio bar and regions */
+ vpci_dev->modern_mem_bar = 2;
+ offset = memory_region_size(&vpci_dev->modern_bar);
+ offset -= memory_region_size(&vpci_dev->notify.mr);
+ vpci_dev->notify.offset = offset;
+ offset -= memory_region_size(&vpci_dev->device.mr);
+ vpci_dev->device.offset = offset;
+ offset -= memory_region_size(&vpci_dev->isr.mr);
+ vpci_dev->isr.offset = offset;
+ offset -= memory_region_size(&vpci_dev->common.mr);
+ vpci_dev->common.offset = offset;
+
/* init virtio bits */
qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
/* force virtio-1.0 */
@@ -94,6 +108,10 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY;
object_property_set_bool(OBJECT(g), true, "realized", errp);
+ /* add stdvga mmio regions */
+ pci_std_vga_mmio_region_init(vga, &vpci_dev->modern_bar,
+ vvga->vga_mrs, true);
+
vga->con = g->scanout[0].con;
graphic_console_set_hwops(vga->con, &virtio_vga_ops, vvga);
}
Arrange things in a way that virtio-vga is both a virtio-1.0 device (acting like virtio-gpu-pci in virtio mode) and fully compatible with stdvga (in vga mode, i.e. when virtio is not enabled). PCI bar #0 is identical for both stdvga and virtio-vga. PCI bar #1 is msi-x for virtio-vga and unused for stdvga, PCI bar #2 is the mmio area, looks like this for virtio-vga: 00000000fe800000-00000000fe87ffff (prio 1, RW): virtio-pci 00000000fe800400-00000000fe80041f (prio 0, RW): vga ioports remapped 00000000fe800500-00000000fe800515 (prio 0, RW): bochs dispi interface 00000000fe800600-00000000fe800607 (prio 0, RW): qemu extended regs 00000000fe83d000-00000000fe83dfff (prio 0, RW): virtio-pci-common 00000000fe83e000-00000000fe83efff (prio 0, RW): virtio-pci-isr 00000000fe83f000-00000000fe83ffff (prio 0, RW): virtio-pci-device 00000000fe840000-00000000fe87ffff (prio 0, RW): virtio-pci-notify PCI bar #2 for stdvga looks this way: 00000000febf0000-00000000febf0fff (prio 1, RW): vga.mmio 00000000febf0400-00000000febf041f (prio 0, RW): vga ioports remapped 00000000febf0500-00000000febf0515 (prio 0, RW): bochs dispi interface 00000000febf0600-00000000febf0607 (prio 0, RW): qemu extended regs i.e. it is smaller, lacks the virtio subregions, and seabios picks a different place because of the size difference. But otherwise the mmio bar is identical. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- hw/display/vga-pci.c | 8 ++++---- hw/display/vga_int.h | 6 ++++++ hw/display/virtio-vga.c | 20 +++++++++++++++++++- 3 files changed, 29 insertions(+), 5 deletions(-)