Vivek Kasireddy <vivek.kasire...@intel.com> writes: > In addition to memfd, a blob resource can also have its backing > storage in a VFIO device region. Therefore, we first need to figure > out if the blob is backed by a VFIO device region or a memfd before > we can call the right API to get a dmabuf fd created. > > So, once we have the ramblock and the associated mr, we rely on > memory_region_is_ram_device() to tell us where the backing storage > is located. If the blob resource is VFIO backed, we try to find the > right VFIO device that contains the blob and then invoke the API > vfio_create_dmabuf(). > > Note that we only call virtio_gpu_remap_udmabuf() if the blob is > backed by a memfd. This is because the VFIO dmabuf implementation > may not support mmap. > > Cc: Marc-André Lureau <marcandre.lur...@redhat.com> > Cc: Alex Bennée <alex.ben...@linaro.org> > Cc: Akihiko Odaki <od...@rsg.ci.i.u-tokyo.ac.jp> > Cc: Dmitry Osipenko <dmitry.osipe...@collabora.com> > Signed-off-by: Vivek Kasireddy <vivek.kasire...@intel.com> > --- > hw/display/virtio-gpu-udmabuf.c | 60 ++++++++++++++++++++++++++++----- > 1 file changed, 52 insertions(+), 8 deletions(-) > > diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c > index d804f321aa..0390a8f488 100644 > --- a/hw/display/virtio-gpu-udmabuf.c > +++ b/hw/display/virtio-gpu-udmabuf.c > @@ -18,6 +18,7 @@ > #include "ui/console.h" > #include "hw/virtio/virtio-gpu.h" > #include "hw/virtio/virtio-gpu-pixman.h" > +#include "hw/vfio/vfio-device.h" > #include "trace.h" > #include "system/ramblock.h" > #include "system/hostmem.h" > @@ -27,6 +28,32 @@ > #include "standard-headers/linux/udmabuf.h" > #include "standard-headers/drm/drm_fourcc.h" > > +static void vfio_create_dmabuf(VFIODevice *vdev, > + struct virtio_gpu_simple_resource *res) > +{ > + res->dmabuf_fd = vfio_device_create_dmabuf(vdev, res->iov, res->iov_cnt); > + if (res->dmabuf_fd < 0) { > + warn_report("%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s", __func__, > + strerror(errno)); > + } > +} > + > +static VFIODevice *vfio_device_lookup(MemoryRegion *mr) > +{ > + VFIODevice *vdev; > + > + if (QLIST_EMPTY(&vfio_device_list)) { > + return NULL; > + } > + > + QLIST_FOREACH(vdev, &vfio_device_list, next) { > + if (vdev->dev == mr->dev) { > + return vdev; > + } > + } > + return NULL; > +} > +
Also fails if VFIO isn't enabled: /usr/bin/ld: libsystem.a.p/hw_display_virtio-gpu-udmabuf.c.o: warning: relocation against `vfio_device_list' in read-only section `.text' /usr/bin/ld: libsystem.a.p/hw_display_virtio-gpu-udmabuf.c.o: in function `vfio_device_lookup': /home/alex/lsrc/qemu.git/builds/all/../../hw/display/virtio-gpu-udmabuf.c:45:(.text+0x313): undefined reference to `vfio_device_list' /usr/bin/ld: libsystem.a.p/hw_display_virtio-gpu-udmabuf.c.o: in function `vfio_create_dmabuf': /home/alex/lsrc/qemu.git/builds/all/../../hw/display/virtio-gpu-udmabuf.c:34:(.text+0x361): undefined reference to `vfio_device_create_dmabuf' /usr/bin/ld: warning: creating DT_TEXTREL in a PIE > static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res) > { > struct udmabuf_create_list *list; > @@ -130,6 +157,9 @@ bool virtio_gpu_have_udmabuf(void) > > void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res) > { > + bool memfd_blob = false; > + ram_addr_t offset; > + RAMBlock *rb; > void *pdata = NULL; > > res->dmabuf_fd = -1; > @@ -137,15 +167,31 @@ void virtio_gpu_init_udmabuf(struct > virtio_gpu_simple_resource *res) > res->iov[0].iov_len < 4096) { > pdata = res->iov[0].iov_base; > } else { > - virtio_gpu_create_udmabuf(res); > + rb = qemu_ram_block_from_host(res->iov[0].iov_base, false, &offset); > + if (rb && memory_region_is_ram_device(rb->mr)) { > + VFIODevice *vdev = vfio_device_lookup(rb->mr); > + > + if (!vdev) { > + warn_report("Could not find device to create dmabuf"); > + return; > + } > + vfio_create_dmabuf(vdev, res); > + } else { > + virtio_gpu_create_udmabuf(res); > + memfd_blob = true; > + } > + > if (res->dmabuf_fd < 0) { > return; > } > - virtio_gpu_remap_udmabuf(res); > - if (!res->remapped) { > - return; > + > + if (memfd_blob) { > + virtio_gpu_remap_udmabuf(res); > + if (!res->remapped) { > + return; > + } > + pdata = res->remapped; > } > - pdata = res->remapped; > } > > res->blob = pdata; > @@ -153,9 +199,7 @@ void virtio_gpu_init_udmabuf(struct > virtio_gpu_simple_resource *res) > > void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res) > { > - if (res->remapped) { > - virtio_gpu_destroy_udmabuf(res); > - } > + virtio_gpu_destroy_udmabuf(res); > } > > static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf) -- Alex Bennée Virtualisation Tech Lead @ Linaro