{"id":2197466,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2197466/?format=json","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.0/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260217214928.2970885-20-dmitry.osipenko@collabora.com>","date":"2026-02-17T21:49:28","name":"[v18,19/19] virtio-gpu: Support mapping hostmem blobs with map_fixed","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"c9c64a696c58f7f9a99e82a22105d40d914a5255","submitter":{"id":83453,"url":"http://patchwork.ozlabs.org/api/1.0/people/83453/?format=json","name":"Dmitry Osipenko","email":"dmitry.osipenko@collabora.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260217214928.2970885-20-dmitry.osipenko@collabora.com/mbox/","series":[{"id":492488,"url":"http://patchwork.ozlabs.org/api/1.0/series/492488/?format=json","date":"2026-02-17T21:49:09","name":"Support virtio-gpu DRM native context and MAP_FIXED API","version":18,"mbox":"http://patchwork.ozlabs.org/series/492488/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2197466/checks/","tags":{},"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=collabora.com header.i=dmitry.osipenko@collabora.com\n header.a=rsa-sha256 header.s=zohomail header.b=KGKjLIjT;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fFthC5Hmfz1xwC\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 08:54:03 +1100 (AEDT)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1vsT0a-0003w4-JG; Tue, 17 Feb 2026 16:53:28 -0500","from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <dmitry.osipenko@collabora.com>)\n id 1vsT0Z-0003pX-0U\n for qemu-devel@nongnu.org; Tue, 17 Feb 2026 16:53:27 -0500","from sender4-pp-e108.zoho.com ([136.143.188.108])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <dmitry.osipenko@collabora.com>)\n id 1vsT0W-0001rG-NA\n for qemu-devel@nongnu.org; Tue, 17 Feb 2026 16:53:26 -0500","by mx.zohomail.com with SMTPS id 1771365187475146.75843478435604;\n Tue, 17 Feb 2026 13:53:07 -0800 (PST)"],"ARC-Seal":"i=1; a=rsa-sha256; t=1771365188; cv=none;\n d=zohomail.com; s=zohoarc;\n b=MjVILhh8RP58jPrK+TAwCEW+llQWky4b7mTjiQv+kunH3sefjjNnyYKII42tPwp4DpliTHlwJ5S0eSDOpWKZoe4nnTB1Etb5eNlWRY4AhQyjSpNZOdGMYt9Dm/Ay/wCmiaSlnQ8X8g86jbYRZxhrxEdV1emJ3CkKUNHvwiocwh8=","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com;\n s=zohoarc; t=1771365188;\n h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To;\n bh=JxDB3fa8HBxXamGwmQA+eB7NcT1g0U+0YSs+Qb1ktas=;\n b=VD9pjDqYdAK/8V3/9bNBPzeptWYfqscBPv3+gbcgGHARcNf3mIAwlebsyTFVU831HF64Er+8fkey4Sy8xPQsybgyeo7SxB9H4NfpczrnTXmVEh4Ge5Ofr/9J1T8nw3uhdU0EyxTGWzMLmHoUDY2YZ35Q8X+EBT3bN1ms2nq6WiM=","ARC-Authentication-Results":"i=1; mx.zohomail.com;\n dkim=pass  header.i=collabora.com;\n spf=pass  smtp.mailfrom=dmitry.osipenko@collabora.com;\n dmarc=pass header.from=<dmitry.osipenko@collabora.com>","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1771365188;\n s=zohomail; d=collabora.com; i=dmitry.osipenko@collabora.com;\n h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To;\n bh=JxDB3fa8HBxXamGwmQA+eB7NcT1g0U+0YSs+Qb1ktas=;\n b=KGKjLIjTubXhemAwROa1SIqKh7FpKD2hx8//SN84N1gtyQRSzRsuLl3zYqV7OE/+\n 7jNt07nmGRsAZ4z1SjVXZkI1ixEyqebEEPB8UXuBzI0c1vLNGa223dJXuc3o44qEpdr\n /hYtdV3ZrIXj9vEAsA7WoGgEARwCw+S+QdgVO330=","From":"Dmitry Osipenko <dmitry.osipenko@collabora.com>","To":"Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>,\n Huang Rui <ray.huang@amd.com>,\n =?utf-8?q?Marc-Andr=C3=A9_Lureau?= <marcandre.lureau@redhat.com>,\n\t=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>,\n Gerd Hoffmann <kraxel@redhat.com>,\n =?utf-8?q?Alex_Benn=C3=A9e?= <alex.bennee@linaro.org>,\n Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>,\n \"Michael S . Tsirkin\" <mst@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>,\n Yiwei Zhang <zzyiwei@gmail.com>, Sergio Lopez Pascual <slp@redhat.com>","Cc":"Gert Wollny <gert.wollny@collabora.com>, qemu-devel@nongnu.org,\n Gurchetan Singh <gurchetansingh@chromium.org>, Alyssa Ross <hi@alyssa.is>,\n\t=?utf-8?q?Roger_Pau_Monn=C3=A9?= <roger.pau@citrix.com>,\n Alex Deucher <alexander.deucher@amd.com>,\n Stefano Stabellini <stefano.stabellini@amd.com>, =?utf-8?q?Christian_K?=\n\t=?utf-8?q?=C3=B6nig?= <christian.koenig@amd.com>,\n Xenia Ragiadakou <xenia.ragiadakou@amd.com>,\n Honglei Huang <honglei1.huang@amd.com>, Julia Zhang <julia.zhang@amd.com>,\n Chen Jiqian <Jiqian.Chen@amd.com>, Rob Clark <robdclark@gmail.com>,\n Robert Beckett <bob.beckett@collabora.com>","Subject":"[PATCH v18 19/19] virtio-gpu: Support mapping hostmem blobs with\n map_fixed","Date":"Wed, 18 Feb 2026 00:49:28 +0300","Message-ID":"<20260217214928.2970885-20-dmitry.osipenko@collabora.com>","X-Mailer":"git-send-email 2.52.0","In-Reply-To":"<20260217214928.2970885-1-dmitry.osipenko@collabora.com>","References":"<20260217214928.2970885-1-dmitry.osipenko@collabora.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-ZohoMailClient":"External","Received-SPF":"pass client-ip=136.143.188.108;\n envelope-from=dmitry.osipenko@collabora.com; helo=sender4-pp-e108.zoho.com","X-Spam_score_int":"-20","X-Spam_score":"-2.1","X-Spam_bar":"--","X-Spam_report":"(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n 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 <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"},"content":"Support mapping virgl blobs to a fixed location of a hostmem memory\nregion using new virglrenderer MAP_FIXED API.\n\nThis new feature closes multiple problems for virtio-gpu on QEMU:\n\n- Having dedicated memory region for each mapped blob works notoriously\nslow due to QEMU's memory region software design built around RCU that\nisn't optimized for frequent removal of the regions\n\n- KVM isn't optimized for a frequent slot changes too\n\n- QEMU/KVM has a limit for a total number of created memory regions,\ncrashing QEMU when limit is reached\n\nThis patch makes virtio-gpu-gl to pre-create a single anonymous memory\nregion covering whole hostmem area to which blobs will be mapped using\nthe MAP_FIXED API.\n\nNot all virgl resources will support mapping at a fixed memory address. For\nthem, we will continue to create individual nested memory sub-regions. In\nparticular, vrend resources may not have MAP_FIXED capability.\n\nVenus and DRM native contexts will largely benefit from the MAP_FIXED\nfeature in terms of performance and stability improvement.\n\nTested-by: Yiwei Zhang <zzyiwei@gmail.com>\nSigned-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>\n---\n hw/display/virtio-gpu-gl.c     | 37 ++++++++++++++++++++-\n hw/display/virtio-gpu-virgl.c  | 59 +++++++++++++++++++++++++++++++++-\n include/hw/virtio/virtio-gpu.h |  3 ++\n 3 files changed, 97 insertions(+), 2 deletions(-)","diff":"diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c\nindex 8b71dd6fc26f..2b7a41c46643 100644\n--- a/hw/display/virtio-gpu-gl.c\n+++ b/hw/display/virtio-gpu-gl.c\n@@ -13,6 +13,7 @@\n \n #include \"qemu/osdep.h\"\n #include \"qemu/iov.h\"\n+#include \"qemu/mmap-alloc.h\"\n #include \"qemu/module.h\"\n #include \"qemu/error-report.h\"\n #include \"qapi/error.h\"\n@@ -106,7 +107,12 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)\n static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp)\n {\n     ERRP_GUARD();\n-    VirtIOGPU *g = VIRTIO_GPU(qdev);\n+    VirtIOGPUBase *b = VIRTIO_GPU_BASE(qdev);\n+    VirtIOGPU *g = VIRTIO_GPU(b);\n+#if !defined(CONFIG_WIN32)\n+    VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);\n+    void *map;\n+#endif\n \n #if HOST_BIG_ENDIAN\n     error_setg(errp, \"virgl is not supported on bigendian platforms\");\n@@ -136,6 +142,24 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp)\n     g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;\n #endif\n \n+#if !defined(CONFIG_WIN32)\n+    if (virtio_gpu_hostmem_enabled(b->conf)) {\n+        map = qemu_ram_mmap(-1, b->conf.hostmem, qemu_real_host_page_size(),\n+                            0, 0);\n+        if (map == MAP_FAILED) {\n+            error_setg_errno(errp, errno,\n+                             \"virgl hostmem region could not be initialized\");\n+            return;\n+        }\n+\n+        gl->hostmem_mmap = map;\n+        memory_region_init_ram_ptr(&gl->hostmem_background, NULL,\n+                                   \"hostmem-background\", b->conf.hostmem,\n+                                   gl->hostmem_mmap);\n+        memory_region_add_subregion(&b->hostmem, 0, &gl->hostmem_background);\n+    }\n+#endif\n+\n     virtio_gpu_device_realize(qdev, errp);\n }\n \n@@ -172,6 +196,17 @@ static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)\n     gl->renderer_state = RS_START;\n \n     g_array_unref(g->capset_ids);\n+\n+    /*\n+     * It is not guaranteed that the memory region will be finalized\n+     * immediately with memory_region_del_subregion(), there can be\n+     * a remaining reference to gl->hostmem_mmap. VirtIO-GPU is not\n+     * hotpluggable, hence no need to worry about the leaked mapping.\n+     *\n+     * The memory_region_del_subregion(gl->hostmem_background) is unnecessary\n+     * because b->hostmem  and gl->hostmem_background belong to the same\n+     * device and will be gone at the same time.\n+     */\n }\n \n static void virtio_gpu_gl_class_init(ObjectClass *klass, const void *data)\ndiff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c\nindex a99c08382b1c..33fa087d4635 100644\n--- a/hw/display/virtio-gpu-virgl.c\n+++ b/hw/display/virtio-gpu-virgl.c\n@@ -41,9 +41,13 @@\n      VIRGL_VERSION_MICRO >= (micro))\n #endif\n \n+#define VIRGL_HAS_MAP_FIXED \\\n+    (VIRGL_CHECK_VERSION(1, 3, 0) && !IS_ENABLED(CONFIG_WIN32))\n+\n struct virtio_gpu_virgl_resource {\n     struct virtio_gpu_simple_resource base;\n     MemoryRegion *mr;\n+    void *map_fixed;\n };\n \n static struct virtio_gpu_virgl_resource *\n@@ -155,6 +159,9 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,\n     g_autofree char *name = NULL;\n     struct virtio_gpu_virgl_hostmem_region *vmr;\n     VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);\n+#if VIRGL_HAS_MAP_FIXED\n+    VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);\n+#endif\n     MemoryRegion *mr;\n     uint64_t size;\n     void *data;\n@@ -165,6 +172,41 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,\n         return -EOPNOTSUPP;\n     }\n \n+#if VIRGL_HAS_MAP_FIXED\n+    /*\n+     * virgl_renderer_resource_map_fixed() allows to create multiple\n+     * mappings of the same resource, while virgl_renderer_resource_map()\n+     * not. Don't allow mapping same resource twice.\n+     */\n+    if (res->map_fixed || res->mr) {\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: failed to map(fixed) virgl resource: already mapped\\n\",\n+                      __func__);\n+        return -EBUSY;\n+    }\n+\n+    ret = virgl_renderer_resource_map_fixed(res->base.resource_id,\n+                                            gl->hostmem_mmap + offset);\n+    switch (ret) {\n+    case 0:\n+        res->map_fixed = gl->hostmem_mmap + offset;\n+        return 0;\n+\n+    case -EOPNOTSUPP:\n+        /*\n+         * MAP_FIXED is unsupported by this resource.\n+         * Mapping falls back to a blob subregion method in that case.\n+         */\n+        break;\n+\n+    default:\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"%s: failed to map(fixed) virgl resource: %s\\n\",\n+                      __func__, strerror(-ret));\n+        return ret;\n+    }\n+#endif\n+\n     ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);\n     if (ret) {\n         qemu_log_mask(LOG_GUEST_ERROR, \"%s: failed to map virgl resource: %s\\n\",\n@@ -181,7 +223,7 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,\n \n     mr = &vmr->mr;\n     memory_region_init_ram_ptr(mr, OBJECT(vmr), \"mr\", size, data);\n-    memory_region_add_subregion(&b->hostmem, offset, mr);\n+    memory_region_add_subregion_overlap(&b->hostmem, offset, mr, 1);\n \n     res->mr = mr;\n \n@@ -200,6 +242,21 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,\n     MemoryRegion *mr = res->mr;\n     int ret;\n \n+#if VIRGL_HAS_MAP_FIXED\n+    if (res->map_fixed) {\n+        if (mmap(res->map_fixed, res->base.blob_size, PROT_READ | PROT_WRITE,\n+                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,\n+                 -1, 0) == MAP_FAILED) {\n+            ret = -errno;\n+            error_report(\"%s: failed to unmap(fixed) virgl resource: %s\",\n+                          __func__, strerror(-ret));\n+            return ret;\n+        }\n+\n+        res->map_fixed = NULL;\n+    }\n+#endif\n+\n     if (!mr) {\n         return 0;\n     }\ndiff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h\nindex 1f509d0d5beb..a48b50d4c825 100644\n--- a/include/hw/virtio/virtio-gpu.h\n+++ b/include/hw/virtio/virtio-gpu.h\n@@ -263,6 +263,9 @@ struct VirtIOGPUGL {\n \n     QEMUBH *async_fence_bh;\n     QSLIST_HEAD(, virtio_gpu_virgl_context_fence) async_fenceq;\n+\n+    MemoryRegion hostmem_background;\n+    void *hostmem_mmap;\n };\n \n struct VhostUserGPU {\n","prefixes":["v18","19/19"]}