From: Albert Esteve <[email protected]>

Expose virtio-media shared memory region 0 (spec 5.22.6.1.6) as a
prefetchable 64-bit PCI BAR (BAR 2) with a VirtIO shm capability.
The size is obtained through GET_SHMEM_CONFIG and requires at least
one shared region. The guest maps host-provisioned MMAP buffers into
this window; QEMU creates a container region on realize, not a
full-sized RAM allocation.

modern-pio-notify is rejected because it claims BAR 2.

vhost-user still needs shareable guest RAM, e.g.:

    -object memory-backend-memfd,id=mem,size=4G,share=on \
    -numa node,memdev=mem

Tested-by: Dorinda Bassey <[email protected]>
Signed-off-by: Albert Esteve <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
Message-ID: <[email protected]>
---
 hw/display/vhost-user-media-pci.c | 35 ++++++++++++++++++++++++++
 hw/display/vhost-user-media.c     | 42 ++++++++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/hw/display/vhost-user-media-pci.c 
b/hw/display/vhost-user-media-pci.c
index 3e09fcfdd0..7681f7505d 100644
--- a/hw/display/vhost-user-media-pci.c
+++ b/hw/display/vhost-user-media-pci.c
@@ -13,12 +13,18 @@
 #include "hw/virtio/vhost-user-media.h"
 #include "hw/virtio/virtio-pci.h"
 
+/* BAR 2 is used for the shared memory region exposed to the guest */
+#define VIRTIO_MEDIA_PCI_SHM_BAR 2
+
+#define VIRTIO_MEDIA_PCI_SHMCAP_ID_SHM 0
+
 #define TYPE_VHOST_USER_MEDIA_PCI "vhost-user-media-pci-base"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserMEDIAPCI, VHOST_USER_MEDIA_PCI)
 
 struct VHostUserMEDIAPCI {
     VirtIOPCIProxy parent_obj;
     VHostUserMEDIA vdev;
+    MemoryRegion shmbar;
 };
 
 static const Property vumedia_pci_properties[] = {
@@ -32,14 +38,43 @@ static void vumedia_pci_realize(VirtIOPCIProxy *vpci_dev, 
Error **errp)
 {
     VHostUserMEDIAPCI *dev = VHOST_USER_MEDIA_PCI(vpci_dev);
     DeviceState *dev_state = DEVICE(&dev->vdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev_state);
+    VirtioSharedMemory *shmem;
+    uint64_t shm_size;
 
     if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
         vpci_dev->nvectors = 1;
     }
 
+    if (vpci_dev->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY) {
+        error_setg(errp, "modern-pio-notify is not supported due to PCI BAR "
+                         "layout limitations");
+        return;
+    }
+
     if (!qdev_realize(dev_state, BUS(&vpci_dev->bus), errp)) {
         return;
     }
+
+    shmem = virtio_find_shmem_region(vdev, VIRTIO_MEDIA_PCI_SHMCAP_ID_SHM);
+    if (!shmem) {
+        error_setg(errp, "vhost-user-media: missing shared memory region");
+        return;
+    }
+    shm_size = memory_region_size(&shmem->mr);
+
+    memory_region_init(&dev->shmbar, OBJECT(vpci_dev),
+                       "vhost-media-pci-shmbar", shm_size);
+    memory_region_add_subregion(&dev->shmbar, 0, &shmem->mr);
+    virtio_pci_add_shm_cap(vpci_dev, VIRTIO_MEDIA_PCI_SHM_BAR, 0,
+                           shm_size, VIRTIO_MEDIA_PCI_SHMCAP_ID_SHM);
+
+    /* After 'realized' so the memory region exists */
+    pci_register_bar(&vpci_dev->pci_dev, VIRTIO_MEDIA_PCI_SHM_BAR,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY |
+                     PCI_BASE_ADDRESS_MEM_PREFETCH |
+                     PCI_BASE_ADDRESS_MEM_TYPE_64,
+                     &dev->shmbar);
 }
 
 static void vumedia_pci_class_init(ObjectClass *klass, const void *data)
diff --git a/hw/display/vhost-user-media.c b/hw/display/vhost-user-media.c
index 14edc7c668..eaf99dc6a2 100644
--- a/hw/display/vhost-user-media.c
+++ b/hw/display/vhost-user-media.c
@@ -19,6 +19,7 @@
 #include "standard-headers/linux/virtio_ids.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/vhost-user-media.h"
+#include "migration/blocker.h"
 
 static const int feature_bits[] = {
     VIRTIO_F_VERSION_1,
@@ -259,8 +260,9 @@ static void vu_media_device_realize(DeviceState *dev, Error 
**errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserMEDIA *media = VHOST_USER_MEDIA(dev);
+    uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS];
     struct vhost_virtqueue *vhost_vqs;
-    int ret;
+    int ret, nregions;
 
     if (!media->conf.chardev.chr) {
         error_setg(errp, "vhost-user-media: chardev is mandatory");
@@ -290,9 +292,47 @@ static void vu_media_device_realize(DeviceState *dev, 
Error **errp)
         return;
     }
 
+    ret = media->vhost_dev.vhost_ops->vhost_get_shmem_config(&media->vhost_dev,
+                                                             &nregions,
+                                                             memory_sizes,
+                                                             errp);
+    if (ret < 0) {
+        goto q_fail;
+    }
+
+    if (!nregions || !memory_sizes[0]) {
+        error_setg(errp, "vhost-user-media: backend did not provide "
+                         "shared memory region 0");
+        goto q_fail;
+    }
+
+    if (memory_sizes[0] % qemu_real_host_page_size() != 0) {
+        error_setg(errp, "shared memory region 0 size must be a multiple "
+                         "of the host page size");
+        goto q_fail;
+    }
+
+    if (media->vhost_dev.migration_blocker == NULL) {
+        error_setg(&media->vhost_dev.migration_blocker,
+                   "Migration disabled: devices with VIRTIO Shared Memory "
+                   "Regions do not support migration yet.");
+        ret = migrate_add_blocker_normal(&media->vhost_dev.migration_blocker,
+                                         errp);
+        if (ret < 0) {
+            goto q_fail;
+        }
+    }
+
+    virtio_new_shmem_region(vdev, 0, memory_sizes[0]);
+
     qemu_chr_fe_set_handlers(&media->conf.chardev, NULL,
                              NULL, vu_media_event,
                              NULL, (void *)dev, NULL, true);
+    return;
+
+q_fail:
+    vhost_dev_cleanup(&media->vhost_dev);
+    do_vhost_user_cleanup(vdev, media, vhost_vqs);
 }
 
 static void vu_media_device_unrealize(DeviceState *dev)
-- 
MST


Reply via email to