@samitouri / QOSamiQemu / commits / b2a279094c

virtio-gpu-virgl: Add virtio-gpu-virgl-hostmem-region type

Commit e27194e087ae ("virtio-gpu-virgl: correct parent for blob memory region") made the name member of MemoryRegion unset, causing a NULL pointer dereference[1]: > Thread 2 "qemu-system-x86" received signal SIGSEGV, Segmentation fault. > (gdb) bt > #0 0x00007ffff56565e2 in __strcmp_evex () at /lib64/libc.so.6 > #1 0x0000555555841bdb in find_fd (head=0x5555572337d0 <cpr_state>, > name=0x0, id=0) at ../migration/cpr.c:68 > #2 cpr_delete_fd (name=name@entry=0x0, id=id@entry=0) at > ../migration/cpr.c:77 > #3 0x000055555582290a in qemu_ram_free (block=0x7ff7e93aa7f0) at > ../system/physmem.c:2615 > #4 0x000055555581ae02 in memory_region_finalize (obj=<optimized out>) > at ../system/memory.c:1816 > #5 0x0000555555a70ab9 in object_deinit (obj=<optimized out>, > type=<optimized out>) at ../qom/object.c:715 > #6 object_finalize (data=0x7ff7e936eff0) at ../qom/object.c:729 > #7 object_unref (objptr=0x7ff7e936eff0) at ../qom/object.c:1232 > #8 0x0000555555814fae in memory_region_unref (mr=<optimized out>) at > ../system/memory.c:1848 > #9 flatview_destroy (view=0x555559ed6c40) at ../system/memory.c:301 > #10 0x0000555555bfc122 in call_rcu_thread (opaque=<optimized out>) at > ../util/rcu.c:324 > #11 0x0000555555bf17a7 in qemu_thread_start (args=0x555557b99520) at > ../util/qemu-thread-posix.c:393 > #12 0x00007ffff556f464 in start_thread () at /lib64/libc.so.6 > #13 0x00007ffff55f25ac in __clone3 () at /lib64/libc.so.6 The intention of the aforementioned commit is to prevent a MemoryRegion from parenting itself while its references is counted indendependently of the device. To achieve the same goal, add a type of QOM objects that count references and parent MemoryRegions. [1] https://lore.kernel.org/qemu-devel/4eb93d7a-1fa9-4b3c-8ad7-a2eb64f025a0@collabora.com/ Cc: qemu-stable@nongnu.org Fixes: e27194e087ae ("virtio-gpu-virgl: correct parent for blob memory region") Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Tested-by: Joelle van Dyne <j@getutm.app> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260214-region-v1-1-229f00ae1f38@rsg.ci.i.u-tokyo.ac.jp>

Akihiko Odaki committed Feb 14, 2026 at 13:33 UTC b2a279094c3b86667969cc645f7fb1087e08dd19
1 file changed +39 -15
hw/display/virtio-gpu-virgl.c
+39 -15
@@ -52,11 +52,17 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
52
53 #if VIRGL_VERSION_MAJOR >= 1
54 struct virtio_gpu_virgl_hostmem_region {
55 + Object parent_obj;
56 MemoryRegion mr;
57 struct VirtIOGPU *g;
58 bool finish_unmapping;
59 };
60
61 +#define TYPE_VIRTIO_GPU_VIRGL_HOSTMEM_REGION "virtio-gpu-virgl-hostmem-region"
62 +
63 +OBJECT_DECLARE_SIMPLE_TYPE(virtio_gpu_virgl_hostmem_region,
64 + VIRTIO_GPU_VIRGL_HOSTMEM_REGION)
65 +
66 static struct virtio_gpu_virgl_hostmem_region *
67 to_hostmem_region(MemoryRegion *mr)
68 {
@@ -70,14 +76,22 @@ static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
76 virtio_gpu_process_cmdq(g);
77 }
78
73 -static void virtio_gpu_virgl_hostmem_region_free(void *obj)
79 +/*
80 + * MR could outlive the resource if MR's reference is held outside of
81 + * virtio-gpu. In order to prevent unmapping resource while MR is alive,
82 + * and thus, making the data pointer invalid, we will block virtio-gpu
83 + * command processing until MR is fully unreferenced and freed.
84 + */
85 +static void virtio_gpu_virgl_hostmem_region_finalize(Object *obj)
86 {
75 - MemoryRegion *mr = MEMORY_REGION(obj);
76 - struct virtio_gpu_virgl_hostmem_region *vmr;
87 + struct virtio_gpu_virgl_hostmem_region *vmr = VIRTIO_GPU_VIRGL_HOSTMEM_REGION(obj);
88 VirtIOGPUBase *b;
89 VirtIOGPUGL *gl;
90
80 - vmr = to_hostmem_region(mr);
91 + if (!vmr->g) {
92 + return;
93 + }
94 +
95 vmr->finish_unmapping = true;
96
97 b = VIRTIO_GPU_BASE(vmr->g);
@@ -92,11 +106,26 @@ static void virtio_gpu_virgl_hostmem_region_free(void *obj)
106 qemu_bh_schedule(gl->cmdq_resume_bh);
107 }
108
109 +static const TypeInfo virtio_gpu_virgl_hostmem_region_info = {
110 + .parent = TYPE_OBJECT,
111 + .name = TYPE_VIRTIO_GPU_VIRGL_HOSTMEM_REGION,
112 + .instance_size = sizeof(struct virtio_gpu_virgl_hostmem_region),
113 + .instance_finalize = virtio_gpu_virgl_hostmem_region_finalize
114 +};
115 +
116 +static void virtio_gpu_virgl_types(void)
117 +{
118 + type_register_static(&virtio_gpu_virgl_hostmem_region_info);
119 +}
120 +
121 +type_init(virtio_gpu_virgl_types)
122 +
123 static int
124 virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
125 struct virtio_gpu_virgl_resource *res,
126 uint64_t offset)
127 {
128 + g_autofree char *name = NULL;
129 struct virtio_gpu_virgl_hostmem_region *vmr;
130 VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
131 MemoryRegion *mr;
@@ -117,21 +146,16 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
146 }
147
148 vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
149 + name = g_strdup_printf("blob[%" PRIu32 "]", res->base.resource_id);
150 + object_initialize_child(OBJECT(g), name, vmr,
151 + TYPE_VIRTIO_GPU_VIRGL_HOSTMEM_REGION);
152 vmr->g = g;
153
154 mr = &vmr->mr;
123 - memory_region_init_ram_ptr(mr, OBJECT(mr), NULL, size, data);
155 + memory_region_init_ram_ptr(mr, OBJECT(vmr), "mr", size, data);
156 memory_region_add_subregion(&b->hostmem, offset, mr);
157 memory_region_set_enabled(mr, true);
158
127 - /*
128 - * MR could outlive the resource if MR's reference is held outside of
129 - * virtio-gpu. In order to prevent unmapping resource while MR is alive,
130 - * and thus, making the data pointer invalid, we will block virtio-gpu
131 - * command processing until MR is fully unreferenced and freed.
132 - */
133 - OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
134 -
159 res->mr = mr;
160
161 trace_virtio_gpu_cmd_res_map_blob(res->base.resource_id, vmr, mr);
@@ -163,7 +187,7 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
187 * 1. Begin async unmapping with memory_region_del_subregion()
188 * and suspend/block cmd processing.
189 * 2. Wait for res->mr to be freed and cmd processing resumed
166 - * asynchronously by virtio_gpu_virgl_hostmem_region_free().
190 + * asynchronously by virtio_gpu_virgl_hostmem_region_finalize().
191 * 3. Finish the unmapping with final virgl_renderer_resource_unmap().
192 */
193 if (vmr->finish_unmapping) {
@@ -186,7 +210,7 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
210 /* memory region owns self res->mr object and frees it by itself */
211 memory_region_set_enabled(mr, false);
212 memory_region_del_subregion(&b->hostmem, mr);
189 - object_unref(OBJECT(mr));
213 + object_unparent(OBJECT(vmr));
214 }
215
216 return 0;