diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 59c0e5d1d7..dead30e626 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -124,6 +124,9 @@ static void vfio_display_dmabuf_update(void *opaque) primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); if (primary == NULL) { + if (dpy->ramfb) { + ramfb_display_update(dpy->con, dpy->ramfb); + } return; } @@ -181,6 +184,9 @@ static int vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp) vdev->dpy->con = graphic_console_init(DEVICE(vdev), 0, &vfio_display_dmabuf_ops, vdev); + if (vdev->enable_ramfb) { + vdev->dpy->ramfb = ramfb_setup(errp); + } return 0; } @@ -228,6 +234,9 @@ static void vfio_display_region_update(void *opaque) return; } if (!plane.drm_format || !plane.size) { + if (dpy->ramfb) { + ramfb_display_update(dpy->con, dpy->ramfb); + } return; } format = qemu_drm_format_to_pixman(plane.drm_format); @@ -300,6 +309,9 @@ static int vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp) vdev->dpy->con = graphic_console_init(DEVICE(vdev), 0, &vfio_display_region_ops, vdev); + if (vdev->enable_ramfb) { + vdev->dpy->ramfb = ramfb_setup(errp); + } return 0; } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 866f0deeb7..a0047f4942 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -3067,6 +3067,10 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) goto out_teardown; } } + if (vdev->enable_ramfb && vdev->dpy == NULL) { + error_setg(errp, "ramfb=on requires display=on"); + goto out_teardown; + } vfio_register_err_notifier(vdev); vfio_register_req_notifier(vdev); @@ -3258,9 +3262,30 @@ static const TypeInfo vfio_pci_dev_info = { }, }; +static Property vfio_pci_dev_nohotplug_properties[] = { + DEFINE_PROP_BOOL("ramfb", VFIOPCIDevice, enable_ramfb, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vfio_pci_nohotplug_dev_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = vfio_pci_dev_nohotplug_properties; + dc->hotpluggable = false; +} + +static const TypeInfo vfio_pci_nohotplug_dev_info = { + .name = "vfio-pci-nohotplug", + .parent = "vfio-pci", + .instance_size = sizeof(VFIOPCIDevice), + .class_init = vfio_pci_nohotplug_dev_class_init, +}; + static void register_vfio_pci_dev_type(void) { type_register_static(&vfio_pci_dev_info); + type_register_static(&vfio_pci_nohotplug_dev_info); } type_init(register_vfio_pci_dev_type) diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index 52b065421a..b1ae4c0754 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -165,6 +165,7 @@ typedef struct VFIOPCIDevice { bool no_geforce_quirks; bool no_kvm_ioeventfd; bool no_vfio_ioeventfd; + bool enable_ramfb; VFIODisplay *dpy; } VFIOPCIDevice; diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 6be9a93f61..e46a28910a 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -26,6 +26,7 @@ #include "qemu/queue.h" #include "qemu/notify.h" #include "ui/console.h" +#include "hw/display/ramfb.h" #ifdef CONFIG_LINUX #include #endif @@ -147,6 +148,7 @@ typedef struct VFIODMABuf { typedef struct VFIODisplay { QemuConsole *con; + RAMFBState *ramfb; struct { VFIORegion buffer; DisplaySurface *surface;