Vivek Kasireddy <[email protected]> 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 <[email protected]>
> Cc: Alex Bennée <[email protected]>
> Cc: Akihiko Odaki <[email protected]>
> Cc: Dmitry Osipenko <[email protected]>
> Signed-off-by: Vivek Kasireddy <[email protected]>
> ---
> 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