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