From nobody Sun Jan 25 12:00:09 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1769149370; cv=none; d=zohomail.com; s=zohoarc; b=YWFN2McjzxVrqqNNusg5pZz3RPZ6kM3EQYPK9t6AzEQMWO3ukYuu8IVl4NFtrSitvFHFMIMu2NEe8wUUBPsLHZYcQhOcq5HhEX8PD0gmrSHG1gBnFVPTPnjBkKpbr5gqFml6dg/fLPm5gb5N2j9b6qpUDKqjLfQnZdWQrRKGEkw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769149370; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=nQiySHMcT41+ApZLmxzxE5vt4aC4yBiFn/UEl6w9380=; b=AcwaFPRk5ANqhWJu/9uKBe4ZRam8oKZ2qvUSDlZCGyS5QyElPpjdcHgIecPqYq99XkO54NuCrckTtYpe9RvcF1k412QtRkt8rCBpA1Yyay4pkK5o3jV1hp6g36uoUTZ3apbm09OF7x6+HUVT0KRrKt0Nadr2EKDnR/MoyamgirQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769149370584805.7942422177733; Thu, 22 Jan 2026 22:22:50 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vjAYo-0003DG-30; Fri, 23 Jan 2026 01:22:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vjAYm-0003Bx-Lk for qemu-devel@nongnu.org; Fri, 23 Jan 2026 01:22:20 -0500 Received: from mgamail.intel.com ([198.175.65.14]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vjAYk-0000sJ-OT for qemu-devel@nongnu.org; Fri, 23 Jan 2026 01:22:20 -0500 Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2026 22:22:07 -0800 Received: from unknown (HELO vkasired-desk2.fm.intel.com) ([10.105.128.132]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2026 22:22:05 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1769149339; x=1800685339; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dOH/gF7JQzm/bUOolKZgzEjapwUscWN6HlBLSOMbf+Y=; b=NVA7BPq2aM6Mv0T+h6oNDdRrc88h1Y9heMbqA9acS1IWQve0CjiY6B5z mjFPyF3y82z3xv5eEWadDuqoX9XshpSQGE1C6JJqZiWhvUr0qO+u9A7bK 9+wuTtuSXHe6fA64fLivH1CHLY2IFetFYWkiglqH7LSyj4JWoVQR0zO7Y ghSOjfYjbt/ufMSDAinUzsKLKQlH8mLW0r0UejKrz5t0RCrYhgs2WT+GU aO6OUJDUn1SDeW32wURGSLveZwmuiAE6EZKPJSOKCn686FFkLH3uWXpql 4CDzPqgWlbMbOuFbx/Q7V+zh+x0DJ2EeymNRiBvLuVBHiHnZqmFjB55l/ Q==; X-CSE-ConnectionGUID: 4QeUSSb0Q/apgaxFyZ9n/A== X-CSE-MsgGUID: qSE17k1PTEmnmPKwhNjuBg== X-IronPort-AV: E=McAfee;i="6800,10657,11679"; a="74254211" X-IronPort-AV: E=Sophos;i="6.21,247,1763452800"; d="scan'208";a="74254211" X-CSE-ConnectionGUID: w6msm5gySf+lcl0A4LBqHw== X-CSE-MsgGUID: xVV5IrQ6Rqek6V1wbXhFkQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,247,1763452800"; d="scan'208";a="207287420" From: Vivek Kasireddy To: qemu-devel@nongnu.org Cc: Vivek Kasireddy , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Akihiko Odaki , Dmitry Osipenko , Alex Williamson , =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Subject: [PATCH v4 8/8] virtio-gpu-dmabuf: Create dmabuf for blobs associated with VFIO devices Date: Thu, 22 Jan 2026 22:17:47 -0800 Message-ID: <20260123062042.568703-9-vivek.kasireddy@intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260123062042.568703-1-vivek.kasireddy@intel.com> References: <20260123062042.568703-1-vivek.kasireddy@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.14; envelope-from=vivek.kasireddy@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.07, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1769149374375154100 In addition to memfd, a blob resource can also have its backing storage in a VFIO device region. Since, there is no effective way to determine where the backing storage is located, we first try to create a dmabuf assuming it is in memfd. If that fails, we try to create a dmabuf assuming it is in VFIO device region. So, we first call virtio_gpu_create_udmabuf() to check if the blob's backing storage is located in a memfd or not. If it is not, we call vfio_create_dmabuf() which identifies the right VFIO device and eventually invokes the vfio_device_create_dmabuf_fd() API to have a dmabuf fd created. Note that in virtio_gpu_remap_dmabuf(), we first try to test if the VFIO dmabuf exporter supports mmap or not. If it doesn't, we use the VFIO device fd directly to create the CPU mapping. While at it, remove the unnecessary rcu_read_lock/rcu_read_unlock from virtio_gpu_create_udmabuf() and also replace warn_report() with qemu_log_mask(). Cc: Marc-Andr=C3=A9 Lureau Cc: Alex Benn=C3=A9e Cc: Akihiko Odaki Cc: Dmitry Osipenko Cc: Alex Williamson Cc: C=C3=A9dric Le Goater Signed-off-by: Vivek Kasireddy --- hw/display/Kconfig | 5 ++ hw/display/virtio-gpu-dmabuf.c | 117 ++++++++++++++++++++++++++++++--- 2 files changed, 113 insertions(+), 9 deletions(-) diff --git a/hw/display/Kconfig b/hw/display/Kconfig index 1e95ab28ef..0d090f25f5 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -106,6 +106,11 @@ config VIRTIO_VGA depends on VIRTIO_PCI select VGA =20 +config VIRTIO_GPU_VFIO_BLOB + bool + default y + depends on VFIO + config VHOST_USER_GPU bool default y diff --git a/hw/display/virtio-gpu-dmabuf.c b/hw/display/virtio-gpu-dmabuf.c index c34d4c85bc..2dfe70d7eb 100644 --- a/hw/display/virtio-gpu-dmabuf.c +++ b/hw/display/virtio-gpu-dmabuf.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,38 @@ #include "standard-headers/linux/udmabuf.h" #include "standard-headers/drm/drm_fourcc.h" =20 +static void vfio_create_dmabuf(struct virtio_gpu_simple_resource *res) +{ +#if defined(VIRTIO_GPU_VFIO_BLOB) + VFIODevice *vbasedev; + RAMBlock *first_rb; + ram_addr_t offset; + + first_rb =3D qemu_ram_block_from_host(res->iov[0].iov_base, false, &of= fset); + if (!first_rb) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Could not find ramblock\n", __func__); + return; + } + + vbasedev =3D vfio_device_lookup(first_rb->mr); + if (!vbasedev) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: No VFIO device found to create dmabuf from\n", + __func__); + return; + } + + res->dmabuf_fd =3D vfio_device_create_dmabuf_fd(vbasedev, + res->iov, res->iov_cnt); + if (res->dmabuf_fd < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: VFIO_DEVICE_FEATURE_DMA_BUF: %s\n", + __func__, strerror(errno)); + } +#endif +} + static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *r= es) { struct udmabuf_create_list *list; @@ -43,10 +76,7 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_= simple_resource *res) sizeof(struct udmabuf_create_item) * res->iov_cnt); =20 for (i =3D 0; i < res->iov_cnt; i++) { - rcu_read_lock(); rb =3D qemu_ram_block_from_host(res->iov[i].iov_base, false, &offs= et); - rcu_read_unlock(); - if (!rb || rb->fd < 0) { g_free(list); return; @@ -62,17 +92,84 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu= _simple_resource *res) =20 res->dmabuf_fd =3D ioctl(udmabuf, UDMABUF_CREATE_LIST, list); if (res->dmabuf_fd < 0) { - warn_report("%s: UDMABUF_CREATE_LIST: %s", __func__, - strerror(errno)); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: UDMABUF_CREATE_LIST: %s\n", + __func__, strerror(errno)); } g_free(list); } =20 +static void *vfio_dmabuf_mmap(struct virtio_gpu_simple_resource *res) +{ + struct vfio_region_info *info =3D NULL; + VFIODevice *vbasedev =3D NULL; + ram_addr_t offset, len =3D 0; + RAMBlock *first_rb, *rb; + void *map, *submap; + int i, ret =3D -1; + + first_rb =3D qemu_ram_block_from_host(res->iov[0].iov_base, false, &of= fset); + if (!first_rb) { + return MAP_FAILED; + } +#if defined(VIRTIO_GPU_VFIO_BLOB) + vbasedev =3D vfio_device_lookup(first_rb->mr); +#endif + if (!vbasedev) { + return MAP_FAILED; + } + + /* + * We first reserve a contiguous chunk of address space for the entire + * dmabuf, then replace it with smaller mappings that correspond to the + * individual segments of the dmabuf. + */ + map =3D mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED, vbasedev->fd= , 0); + if (map =3D=3D MAP_FAILED) { + return map; + } + + for (i =3D 0; i < res->iov_cnt; i++) { + rb =3D qemu_ram_block_from_host(res->iov[i].iov_base, false, &offs= et); + if (rb !=3D first_rb) { + goto err; + } +#if defined(VIRTIO_GPU_VFIO_BLOB) + ret =3D vfio_get_region_index_from_mr(rb->mr); + if (ret < 0) { + goto err; + } + + ret =3D vfio_device_get_region_info(vbasedev, ret, &info); +#endif + if (ret < 0 || !info) { + goto err; + } + + submap =3D mmap(map + len, res->iov[i].iov_len, PROT_READ, + MAP_SHARED | MAP_FIXED, vbasedev->fd, + info->offset + offset); + if (submap =3D=3D MAP_FAILED) { + goto err; + } + + len +=3D res->iov[i].iov_len; + } + return map; +err: + munmap(map, res->blob_size); + return MAP_FAILED; +} + static void virtio_gpu_remap_dmabuf(struct virtio_gpu_simple_resource *res) { res->remapped =3D mmap(NULL, res->blob_size, PROT_READ, MAP_SHARED, res->dmabuf_fd, 0); if (res->remapped =3D=3D MAP_FAILED) { + res->remapped =3D vfio_dmabuf_mmap(res); + if (res->remapped !=3D MAP_FAILED) { + return; + } warn_report("%s: dmabuf mmap failed: %s", __func__, strerror(errno)); res->remapped =3D NULL; @@ -139,8 +236,12 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_r= esource *res) } else { virtio_gpu_create_udmabuf(res); if (res->dmabuf_fd < 0) { - return; + vfio_create_dmabuf(res); + if (res->dmabuf_fd < 0) { + return; + } } + virtio_gpu_remap_dmabuf(res); if (!res->remapped) { return; @@ -153,9 +254,7 @@ void virtio_gpu_init_dmabuf(struct virtio_gpu_simple_re= source *res) =20 void virtio_gpu_fini_dmabuf(struct virtio_gpu_simple_resource *res) { - if (res->remapped) { - virtio_gpu_destroy_dmabuf(res); - } + virtio_gpu_destroy_dmabuf(res); } =20 static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf) --=20 2.50.1