diff --git a/devicemodel/core/hugetlb.c b/devicemodel/core/hugetlb.c index 5e294c90a..6e8a2a580 100644 --- a/devicemodel/core/hugetlb.c +++ b/devicemodel/core/hugetlb.c @@ -881,3 +881,35 @@ vm_find_memfd_region(struct vmctx *ctx, vm_paddr_t gpa, return ret; } + +bool vm_allow_dmabuf(struct vmctx *ctx) +{ + uint32_t mem_flags; + + mem_flags = 0; + if (ctx->highmem) { + /* Check the highmem is used by HUGETLB_LV1/HUGETLB_LV2 */ + if ((hugetlb_priv[HUGETLB_LV1].fd > 0) && + (hugetlb_priv[HUGETLB_LV1].highmem)) + mem_flags |= 1; + if ((hugetlb_priv[HUGETLB_LV2].fd > 0) && + (hugetlb_priv[HUGETLB_LV2].highmem)) + mem_flags |= 0x02; + if (mem_flags == 0x03) + return false; + } + + if (ctx->lowmem) { + /* Check the lowhmem is used by HUGETLB_LV1/HUGETLB_LV2 */ + mem_flags = 0; + if ((hugetlb_priv[HUGETLB_LV1].fd > 0) && + (hugetlb_priv[HUGETLB_LV1].lowmem)) + mem_flags |= 1; + if ((hugetlb_priv[HUGETLB_LV2].fd > 0) && + (hugetlb_priv[HUGETLB_LV2].lowmem)) + mem_flags |= 0x02; + if (mem_flags == 0x03) + return false; + } + return true; +} diff --git a/devicemodel/hw/pci/virtio/virtio_gpu.c b/devicemodel/hw/pci/virtio/virtio_gpu.c index 667bc0fe1..5631040ce 100644 --- a/devicemodel/hw/pci/virtio/virtio_gpu.c +++ b/devicemodel/hw/pci/virtio/virtio_gpu.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "dm.h" #include "pci_core.h" @@ -1468,6 +1470,40 @@ virtio_gpu_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) gpu->base.mtx = &gpu->mtx; gpu->base.device_caps = VIRTIO_GPU_S_HOSTCAPS; + if (vm_allow_dmabuf(gpu->base.dev->vmctx)) { + FILE *fp; + char buf[16]; + int list_limit; + + gpu->is_blob_supported = true; + /* Now the memfd is used by default and it + * is based on Huge_tlb. + * But if both 2M and 1G are used for memory, + * it can't support dmabuf as it is difficult to + * determine whether one memory region is based on 2M or 1G. + */ + fp = fopen("/sys/module/udmabuf/parameters/list_limit", "r"); + if (fp) { + memset(buf, 0, sizeof(buf)); + rc = fread(buf, sizeof(buf), 1, fp); + fclose(fp); + list_limit = atoi(buf); + if (list_limit < 4096) { + pr_info("udmabuf.list_limit=%d in kernel is too small. " + "Please add udmabuf.list_limit=4096 in kernel " + "boot option to use GPU zero-copy.\n", + list_limit); + gpu->is_blob_supported = false; + } + } else { + pr_info("Zero-copy is disabled. Please check that " + "CONFIG_UDMABUF is enabled in the kernel config.\n"); + gpu->is_blob_supported = false; + } + if (gpu->is_blob_supported) + gpu->base.device_caps |= (1UL << VIRTIO_GPU_F_RESOURCE_BLOB); + } + /* set queue size */ gpu->vq[VIRTIO_GPU_CONTROLQ].qsize = VIRTIO_GPU_RINGSZ; gpu->vq[VIRTIO_GPU_CONTROLQ].notify = virtio_gpu_notify_controlq; diff --git a/devicemodel/include/vmmapi.h b/devicemodel/include/vmmapi.h index 1914b3105..d6a6e0a78 100644 --- a/devicemodel/include/vmmapi.h +++ b/devicemodel/include/vmmapi.h @@ -95,6 +95,7 @@ struct vm_mem_region { }; bool vm_find_memfd_region(struct vmctx *ctx, vm_paddr_t gpa, struct vm_mem_region *ret_region); +bool vm_allow_dmabuf(struct vmctx *ctx); /* * Create a device memory segment identified by 'segid'. *