Re: [PATCH v17 00/13] Support blob memory and venus on qemu

2024-09-01 Thread Dmitry Osipenko
On 8/27/24 12:57, Alex Bennée wrote:
> Dmitry Osipenko  writes:
> 
>> Hello,
>>
>> This series enables Vulkan Venus context support on virtio-gpu.
>>
>> All virglrender and almost all Linux kernel prerequisite changes
>> needed by Venus are already in upstream. For kernel there is a pending
>> KVM patchset that fixes mapping of compound pages needed for DRM drivers
>> using TTM or huge pages [1], othewrwise hostmem blob mapping will fail
>> with a KVM error from Qemu.
>>
>> [1] https://lore.kernel.org/all/20240726235234.228822-1-sea...@google.com/
>>
>> On guest you'll need to use recent Mesa 24.2+ version containing patch
>> that removes dependency on cross-device feature from Venus that isn't
>> supported by Qemu [2].
>>
>> [2]
>> https://gitlab.freedesktop.org/mesa/mesa/-/commit/087e9a96d13155e26987befae78b6ccbb7ae242b
> 
> I've expanded the set of working tests so:
> 
> x86 host, Intel GPU
> 
>  x86/kvm Trixie guest + latest mesa - works
>  aarch64/tcg buildroot guest - works
> 
> Aarch64 host, AMD GPU
> 
>  x86/tcg Trixies guest + latest mesa - works
>  aarch64/kvm buildroot guest - works
> 
> As the Aarch64 HW I'm testing on (AVA Devbox) needs additional patches
> on top of Sean's series to deal with the busted Altra PCI which I
> provide here:
> 
>  
> https://git.linaro.org/people/alex.bennee/linux.git/log/?h=review/pfn-references-v12-with-altra-tweaks
> 
> Anyway I'll re-state:
> 
>   Tested-by: Alex Bennée 
> 
> And I think this series is ready to merge once the tree re-opens.

Thanks for the update, nice to see that you nailed the ARM problem

-- 
Best regards,
Dmitry




[PATCH v17 10/13] virtio-gpu: Support suspension of commands processing

2024-08-22 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events | 1 +
 hw/display/virtio-gpu.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index e212710284ae..d26d663f9638 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -55,6 +55,7 @@ virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 
0x%" PRIx64 ", type
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
 virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
 virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
+virtio_gpu_cmd_suspended(uint32_t cmd) "cmd 0x%x"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 24608338d7ea..5015f17f9242 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1053,6 +1053,12 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+trace_virtio_gpu_cmd_suspended(cmd->cmd_hdr.type);
+break;
+}
+
 QTAILQ_REMOVE(&g->cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.45.2




[PATCH v17 12/13] virtio-gpu: Register capsets dynamically

2024-08-22 Thread Dmitry Osipenko
From: Pierre-Eric Pelloux-Prayer 

virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
like Venus and DRM capsets. Register capsets dynamically to avoid that problem.

Reviewed-by: Manos Pitsidianakis 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Pierre-Eric Pelloux-Prayer 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  6 --
 hw/display/virtio-gpu-virgl.c  | 33 +
 include/hw/virtio/virtio-gpu.h |  4 +++-
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index f2555673a18e..e859c0dff055 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -144,8 +144,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 }
 
 g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
-VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
-virtio_gpu_virgl_get_num_capsets(g);
+g->capset_ids = virtio_gpu_virgl_get_capsets(g);
+VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
 
 #if VIRGL_VERSION_MAJOR >= 1
 g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
@@ -177,6 +177,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 }
 
 gl->renderer_state = RS_START;
+
+g_array_unref(g->capset_ids);
 }
 
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b2f4e215a7ad..5a881c58a11d 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -622,19 +622,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 VIRTIO_GPU_FILL_CMD(info);
 
 memset(&resp, 0, sizeof(resp));
-if (info.capset_index == 0) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
-virgl_renderer_get_cap_set(resp.capset_id,
-   &resp.capset_max_version,
-   &resp.capset_max_size);
-} else if (info.capset_index == 1) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+
+if (info.capset_index < g->capset_ids->len) {
+resp.capset_id = g_array_index(g->capset_ids, uint32_t,
+   info.capset_index);
 virgl_renderer_get_cap_set(resp.capset_id,
&resp.capset_max_version,
&resp.capset_max_size);
-} else {
-resp.capset_max_version = 0;
-resp.capset_max_size = 0;
 }
 resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
 virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
@@ -1160,12 +1154,27 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t capset_id)
+{
+g_array_append_val(capset_ids, capset_id);
+}
+
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
 uint32_t capset2_max_ver, capset2_max_size;
+GArray *capset_ids;
+
+capset_ids = g_array_new(false, false, sizeof(uint32_t));
+
+/* VIRGL is always supported. */
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
+
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
   &capset2_max_ver,
   &capset2_max_size);
+if (capset2_max_ver) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
+}
 
-return capset2_max_ver ? 2 : 1;
+return capset_ids;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 775005abb337..83232f4b4bfa 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -209,6 +209,8 @@ struct VirtIOGPU {
 QTAILQ_HEAD(, VGPUDMABuf) bufs;
 VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
 } dmabuf;
+
+GArray *capset_ids;
 };
 
 struct VirtIOGPUClass {
@@ -354,6 +356,6 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.45.2




[PATCH v17 13/13] virtio-gpu: Support Venus context

2024-08-22 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 docs/system/devices/virtio-gpu.rst | 11 +++
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 15 +++
 include/hw/virtio/virtio-gpu.h |  3 +++
 5 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/docs/system/devices/virtio-gpu.rst 
b/docs/system/devices/virtio-gpu.rst
index cb73dd799858..b7eb0fc0e727 100644
--- a/docs/system/devices/virtio-gpu.rst
+++ b/docs/system/devices/virtio-gpu.rst
@@ -71,6 +71,17 @@ representation back to OpenGL API calls.
 .. _Gallium3D: https://www.freedesktop.org/wiki/Software/gallium/
 .. _virglrenderer: https://gitlab.freedesktop.org/virgl/virglrenderer/
 
+Translation of Vulkan API calls is supported since release of `virglrenderer`_
+v1.0.0 using `venus`_ protocol. ``Venus`` virtio-gpu capability set ("capset")
+requires host blob support (``hostmem`` and ``blob`` fields) and should
+be enabled using ``venus`` field. The ``hostmem`` field specifies the size
+of virtio-gpu host memory window. This is typically between 256M and 8G.
+
+.. parsed-literal::
+-device virtio-gpu-gl,hostmem=8G,blob=true,venus=true
+
+.. _venus: https://gitlab.freedesktop.org/virgl/venus-protocol/
+
 virtio-gpu rutabaga
 ---
 
diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index e859c0dff055..7c0e448b4661 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -157,6 +157,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 5a881c58a11d..eedae7357f1a 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1128,6 +1128,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#if VIRGL_VERSION_MAJOR >= 1
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs);
 if (ret != 0) {
@@ -1161,7 +1166,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1170,11 +1175,20 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  &capset2_max_ver,
-  &capset2_max_size);
-if (capset2_max_ver) {
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 6a9eb880ebbf..0d1de7dc398c 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1506,6 +1506,21 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef VIRGL_VERSION_MAJOR
+#if VIRGL_VERSION_MAJOR >= 1
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+#endif
+}
+
 if (!virt

[PATCH v17 11/13] virtio-gpu: Handle resource blob commands

2024-08-22 Thread Dmitry Osipenko
From: Robert Beckett 

Support BLOB resources creation, mapping, unmapping and set-scanout by
calling the new stable virglrenderer 0.10 interface. Only enabled when
available and via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Robert Beckett 
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |   3 +
 hw/display/virtio-gpu-virgl.c  | 414 -
 hw/display/virtio-gpu.c|  18 +-
 include/hw/virtio/virtio-gpu.h |   9 +
 4 files changed, 434 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index bf87ba423283..f2555673a18e 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -166,6 +166,9 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
 
 if (gl->renderer_state >= RS_INITED) {
+#if VIRGL_VERSION_MAJOR >= 1
+qemu_bh_delete(gl->cmdq_resume_bh);
+#endif
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 timer_free(gl->print_stats);
 }
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 3ffea478e723..b2f4e215a7ad 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -24,6 +26,7 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -47,6 +50,145 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#if VIRGL_VERSION_MAJOR >= 1
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+bool finish_unmapping;
+};
+
+static struct virtio_gpu_virgl_hostmem_region *
+to_hostmem_region(MemoryRegion *mr)
+{
+return container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+}
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+VirtIOGPUGL *gl;
+
+vmr = to_hostmem_region(mr);
+vmr->finish_unmapping = true;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+gl = VIRTIO_GPU_GL(vmr->g);
+qemu_bh_schedule(gl->cmdq_resume_bh);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->g = g;
+
+mr = &vmr->mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(&b->hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
+ struct virtio_gpu_virgl_resource *res,
+ bool *cmd_suspended)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+

[PATCH v17 05/13] virtio-gpu: Unrealize GL device

2024-08-22 Thread Dmitry Osipenko
Even though GL GPU doesn't support hotplugging today, free virgl
resources when GL device is unrealized. For consistency.

Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index ea3413aa566f..753b35ed69fd 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -156,6 +156,22 @@ static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
+{
+VirtIOGPU *g = VIRTIO_GPU(qdev);
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
+
+if (gl->renderer_state >= RS_INITED) {
+if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
+timer_free(gl->print_stats);
+}
+timer_free(gl->fence_poll);
+virgl_renderer_cleanup(NULL);
+}
+
+gl->renderer_state = RS_START;
+}
+
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -169,6 +185,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
void *data)
 vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
 
 vdc->realize = virtio_gpu_gl_device_realize;
+vdc->unrealize = virtio_gpu_gl_device_unrealize;
 vdc->reset = virtio_gpu_gl_reset;
 device_class_set_props(dc, virtio_gpu_gl_properties);
 }
-- 
2.45.2




[PATCH v17 07/13] virtio-gpu: Support context-init feature with virglrenderer

2024-08-22 Thread Dmitry Osipenko
From: Huang Rui 

Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
feature flags. Expose this feature and support creating virglrenderer
context with flags using context_id if libvirglrenderer is new enough.

Originally-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c|  4 
 hw/display/virtio-gpu-virgl.c | 20 ++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 753b35ed69fd..bf87ba423283 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -147,6 +147,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
*qdev, Error **errp)
 VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
 virtio_gpu_virgl_get_num_capsets(g);
 
+#if VIRGL_VERSION_MAJOR >= 1
+g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
+#endif
+
 virtio_gpu_device_realize(qdev, errp);
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index ca6f4d6cbb58..b3aa444bcfa5 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
 trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
 cc.debug_name);
 
-virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
-  cc.debug_name);
+if (cc.context_init) {
+if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+return;
+}
+
+#if VIRGL_VERSION_MAJOR >= 1
+virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
+ cc.context_init,
+ cc.nlen,
+ cc.debug_name);
+return;
+#endif
+}
+
+virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
 }
 
 static void virgl_cmd_context_destroy(VirtIOGPU *g,
-- 
2.45.2




[PATCH v17 08/13] virtio-gpu: Don't require udmabuf when blobs and virgl are enabled

2024-08-22 Thread Dmitry Osipenko
The udmabuf usage is mandatory when virgl is disabled and blobs feature
enabled in the Qemu machine configuration. If virgl and blobs are enabled,
then udmabuf requirement is optional. Since udmabuf isn't widely supported
by a popular Linux distros today, let's relax the udmabuf requirement for
blobs=on,virgl=on. Now, a full-featured virtio-gpu acceleration is
available to Qemu users without a need to have udmabuf available in the
system.

Reviewed-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 60dfed87765b..24608338d7ea 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1484,6 +1484,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 
 if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
 if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
+!virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
 !virtio_gpu_have_udmabuf()) {
 error_setg(errp, "need rutabaga or udmabuf for blob resources");
 return;
-- 
2.45.2




[PATCH v17 06/13] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-08-22 Thread Dmitry Osipenko
New virglrerenderer features were stabilized with release of v1.0.0.
Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
with pre-release development versions of libvirglerender. Use virglrenderer
version to decide reliably which virgl features are available.

Reviewed-by: Alex Bennée 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 2 +-
 meson.build   | 5 +
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index a63d1f540f04..ca6f4d6cbb58 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -171,7 +171,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
 struct virgl_renderer_resource_info info;
 void *d3d_tex2d = NULL;
 
-#ifdef HAVE_VIRGL_D3D_INFO_EXT
+#if VIRGL_VERSION_MAJOR >= 1
 struct virgl_renderer_resource_info_ext ext;
 memset(&ext, 0, sizeof(ext));
 ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
diff --git a/meson.build b/meson.build
index fbda17c987e2..8bc7ee47da2c 100644
--- a/meson.build
+++ b/meson.build
@@ -2388,10 +2388,7 @@ config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.found()
-  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
-   cc.has_member('struct 
virgl_renderer_resource_info_ext', 'd3d_tex2d',
- prefix: '#include ',
- dependencies: virgl))
+  config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.45.2




[PATCH v17 09/13] virtio-gpu: Add virgl resource management

2024-08-22 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b3aa444bcfa5..3ffea478e723 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
&res_iovs,
&num_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_i

[PATCH v17 04/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-08-22 Thread Dmitry Osipenko
virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
return code and don't execute virtio commands on error. Failed
virtio_gpu_virgl_init() will result in a timed out virtio commands
for a guest OS.

Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 30 ++
 include/hw/virtio/virtio-gpu.h | 11 +--
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 29d20b01321c..ea3413aa566f 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  struct virtio_gpu_scanout *s,
  uint32_t resource_id)
 {
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 uint32_t width, height;
 uint32_t pixels, *data;
 
+if (gl->renderer_state != RS_INITED) {
+return;
+}
+
 data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
 if (!data) {
 return;
@@ -65,13 +70,22 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, 
VirtQueue *vq)
 return;
 }
 
-if (!gl->renderer_inited) {
-virtio_gpu_virgl_init(g);
-gl->renderer_inited = true;
-}
-if (gl->renderer_reset) {
-gl->renderer_reset = false;
+switch (gl->renderer_state) {
+case RS_RESET:
 virtio_gpu_virgl_reset(g);
+/* fallthrough */
+case RS_START:
+if (virtio_gpu_virgl_init(g)) {
+gl->renderer_state = RS_INIT_FAILED;
+return;
+}
+
+gl->renderer_state = RS_INITED;
+break;
+case RS_INIT_FAILED:
+return;
+case RS_INITED:
+break;
 }
 
 cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
@@ -98,9 +112,9 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
  * GL functions must be called with the associated GL context in main
  * thread, and when the renderer is unblocked.
  */
-if (gl->renderer_inited && !gl->renderer_reset) {
+if (gl->renderer_state == RS_INITED) {
 virtio_gpu_virgl_reset_scanout(g);
-gl->renderer_reset = true;
+gl->renderer_state = RS_RESET;
 }
 }
 
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7ff989a45a5c..6e71d799e5da 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -224,11 +224,18 @@ struct VirtIOGPUClass {
  Error **errp);
 };
 
+/* VirtIOGPUGL renderer states */
+typedef enum {
+RS_START,   /* starting state */
+RS_INIT_FAILED, /* failed initialisation */
+RS_INITED,  /* initialised and working */
+RS_RESET,   /* inited and reset pending, moves to start after reset */
+} RenderState;
+
 struct VirtIOGPUGL {
 struct VirtIOGPU parent_obj;
 
-bool renderer_inited;
-bool renderer_reset;
+RenderState renderer_state;
 
 QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
-- 
2.45.2




[PATCH v17 03/13] virtio-gpu: Move print_stats timer to VirtIOGPUGL

2024-08-22 Thread Dmitry Osipenko
Move print_stats timer to VirtIOGPUGL for consistency with
cmdq_resume_bh and fence_poll that are used only by GL device.

Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 10 ++
 include/hw/virtio/virtio-gpu.h |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 91dce90f9176..a63d1f540f04 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -574,6 +574,7 @@ static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
 static void virtio_gpu_print_stats(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 if (g->stats.requests) {
 fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
@@ -588,7 +589,7 @@ static void virtio_gpu_print_stats(void *opaque)
 } else {
 fprintf(stderr, "stats: idle\r");
 }
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+timer_mod(gl->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 static void virtio_gpu_fence_poll(void *opaque)
@@ -651,9 +652,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
   virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
-  virtio_gpu_print_stats, g);
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 
1000);
+gl->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+   virtio_gpu_print_stats, g);
+timer_mod(gl->print_stats,
+  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 return 0;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index bc69fd78a440..7ff989a45a5c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *print_stats;
 
 uint32_t inflight;
 struct {
@@ -232,6 +231,7 @@ struct VirtIOGPUGL {
 bool renderer_reset;
 
 QEMUTimer *fence_poll;
+QEMUTimer *print_stats;
 };
 
 struct VhostUserGPU {
-- 
2.45.2




[PATCH v17 02/13] virtio-gpu: Move fence_poll timer to VirtIOGPUGL

2024-08-22 Thread Dmitry Osipenko
Move fence_poll timer to VirtIOGPUGL for consistency with cmdq_resume_bh
that are used only by GL device.

Reviewed-by: Akihiko Odaki 
Reviewed-by: Marc-André Lureau 
Reviewed-by: Alex Bennée 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 8 +---
 include/hw/virtio/virtio-gpu.h | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 14091b191ec0..91dce90f9176 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -594,11 +594,12 @@ static void virtio_gpu_print_stats(void *opaque)
 static void virtio_gpu_fence_poll(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 virgl_renderer_poll();
 virtio_gpu_process_cmdq(g);
 if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
-timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
+timer_mod(gl->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
 }
 }
 
@@ -626,6 +627,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 {
 int ret;
 uint32_t flags = 0;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 if (qemu_egl_display) {
@@ -645,8 +647,8 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return ret;
 }
 
-g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- virtio_gpu_fence_poll, g);
+gl->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+  virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a7a..bc69fd78a440 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
 
 uint32_t inflight;
@@ -231,6 +230,8 @@ struct VirtIOGPUGL {
 
 bool renderer_inited;
 bool renderer_reset;
+
+QEMUTimer *fence_poll;
 };
 
 struct VhostUserGPU {
-- 
2.45.2




[PATCH v17 00/13] Support blob memory and venus on qemu

2024-08-22 Thread Dmitry Osipenko
 configrable via new virtio-gpu device
  "vulkan=true" flag, suggested by Marc-André Lureau. The flag is disabled
  by default because it requires blob and hostmem options to be enabled
  and configured

Changes from V5 to V6

- Move macros configurations under virgl.found() and rename
  HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS.

- Handle the case while context_init is disabled.

- Enable context_init by default.

- Move virtio_gpu_virgl_resource_unmap() into
  virgl_cmd_resource_unmap_blob().

- Introduce new struct virgl_gpu_resource to store virgl specific members.

- Remove erro handling of g_new0, because glib will abort() on OOM.

- Set resource uuid as option.

- Implement optional subsection of vmstate_virtio_gpu_resource_uuid_state
  for virtio live migration.

- Use g_int_hash/g_int_equal instead of the default

- Add scanout_blob function for virtio-gpu-virgl

- Resolve the memory leak on virtio-gpu-virgl

- Remove the unstable API flags check because virglrenderer is already 1.0

- Squash the render server flag support into "Initialize Venus"

Changes from V4 (virtio gpu V4) to V5

- Inverted patch 5 and 6 because we should configure
  HAVE_VIRGL_CONTEXT_INIT firstly.

- Validate owner of memory region to avoid slowing down DMA.

- Use memory_region_init_ram_ptr() instead of
  memory_region_init_ram_device_ptr().

- Adjust sequence to allocate gpu resource before virglrender resource
  creation

- Add virtio migration handling for uuid.

- Send kernel patch to define VIRTIO_GPU_CAPSET_VENUS.
  https://lore.kernel.org/lkml/20230915105918.3763061-1-ray.hu...@amd.com/

- Add meson check to make sure unstable APIs defined from 0.9.0.

Changes from V1 to V2 (virtio gpu V4)

- Remove unused #include "hw/virtio/virtio-iommu.h"

- Add a local function, called virgl_resource_destroy(), that is used
  to release a vgpu resource on error paths and in resource_unref.

- Remove virtio_gpu_virgl_resource_unmap from
  virtio_gpu_cleanup_mapping(),
  since this function won't be called on blob resources and also because
  blob resources are unmapped via virgl_cmd_resource_unmap_blob().

- In virgl_cmd_resource_create_blob(), do proper cleanup in error paths
  and move QTAILQ_INSERT_HEAD(&g->reslist, res, next) after the resource
  has been fully initialized.

- Memory region has a different life-cycle from virtio gpu resources
  i.e. cannot be released synchronously along with the vgpu resource.
  So, here the field "region" was changed to a pointer and is allocated
  dynamically when the blob is mapped.
  Also, since the pointer can be used to indicate whether the blob
  is mapped, the explicite field "mapped" was removed.

- In virgl_cmd_resource_map_blob(), add check on the value of
  res->region, to prevent beeing called twice on the same resource.

- Add a patch to enable automatic deallocation of memory regions to resolve
  use-after-free memory corruption with a reference.


Antonio Caggiano (1):
  virtio-gpu: Support Venus context

Dmitry Osipenko (8):
  virtio-gpu: Use trace events for tracking number of in-flight fences
  virtio-gpu: Move fence_poll timer to VirtIOGPUGL
  virtio-gpu: Move print_stats timer to VirtIOGPUGL
  virtio-gpu: Handle virtio_gpu_virgl_init() failure
  virtio-gpu: Unrealize GL device
  virtio-gpu: Use pkgconfig version to decide which virgl features are
available
  virtio-gpu: Don't require udmabuf when blobs and virgl are enabled
  virtio-gpu: Support suspension of commands processing

Huang Rui (2):
  virtio-gpu: Support context-init feature with virglrenderer
  virtio-gpu: Add virgl resource management

Pierre-Eric Pelloux-Prayer (1):
  virtio-gpu: Register capsets dynamically

Robert Beckett (1):
  virtio-gpu: Handle resource blob commands

 docs/system/devices/virtio-gpu.rst |  11 +
 hw/display/trace-events|   3 +
 hw/display/virtio-gpu-gl.c |  62 ++-
 hw/display/virtio-gpu-virgl.c  | 585 +++--
 hw/display/virtio-gpu.c|  44 ++-
 include/hw/virtio/virtio-gpu.h |  32 +-
 meson.build|   5 +-
 7 files changed, 685 insertions(+), 57 deletions(-)

-- 
2.45.2




[PATCH v17 01/13] virtio-gpu: Use trace events for tracking number of in-flight fences

2024-08-22 Thread Dmitry Osipenko
Replace printf's used for tracking of in-flight fence inc/dec events
with tracing, for consistency with the rest of virtio-gpu code that
uses tracing.

Suggested-by: Marc-André Lureau 
Reviewed-by: Marc-André Lureau 
Reviewed-by: Akihiko Odaki 
Reviewed-by: Alex Bennée 
Tested-by: Alex Bennée 
Acked-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events   | 2 ++
 hw/display/virtio-gpu-virgl.c | 2 +-
 hw/display/virtio-gpu.c   | 4 ++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index 781f8a33203b..e212710284ae 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -53,6 +53,8 @@ virtio_gpu_cmd_ctx_submit(uint32_t ctx, uint32_t size) "ctx 
0x%x, size %d"
 virtio_gpu_update_cursor(uint32_t scanout, uint32_t x, uint32_t y, const char 
*type, uint32_t res) "scanout %d, x %d, y %d, %s, res 0x%x"
 virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", 
type 0x%x"
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
+virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
+virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9f34d0e6619c..14091b191ec0 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -525,7 +525,7 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 3281842bfe1b..60dfed87765b 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1065,7 +1065,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 if (g->stats.max_inflight < g->inflight) {
 g->stats.max_inflight = g->inflight;
 }
-fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
+trace_virtio_gpu_inc_inflight_fences(g->inflight);
 }
 } else {
 g_free(cmd);
@@ -1085,7 +1085,7 @@ static void virtio_gpu_process_fenceq(VirtIOGPU *g)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
-- 
2.45.2




Re: [PATCH v16 00/13] Support blob memory and venus on qemu

2024-08-22 Thread Dmitry Osipenko
On 8/22/24 16:13, Alex Bennée wrote:
> "Michael S. Tsirkin"  writes:
> 
>> On Sun, Jun 23, 2024 at 06:23:30PM +0300, Dmitry Osipenko wrote:
>>> Hello,
>>>
>>> This series enables Vulkan Venus context support on virtio-gpu.
>>>
>>> All virglrender and almost all Linux kernel prerequisite changes
>>> needed by Venus are already in upstream. For kernel there is a pending
>>> KVM patchset that fixes mapping of compound pages needed for DRM drivers
>>> using TTM [1], othewrwise hostmem blob mapping will fail with a KVM error
>>> from Qemu.
>>
>>
>> I'd like to see a Tested-by from Alex Bennée for this -
>> he's been testing v14 last as far as I could see.
> 
> I've posted it on the top. Broadly x86 and Arm work on my x86 host. So
> far my Arm host only runs the x86 image with the AMD card OK.
> 
> I've updated my test images so you can try them:
> 
>   https://fileserver.linaro.org/s/ce5jXBFinPxtEdx
> 
> See the notes on the readme on how to run.

Thanks, Alex! I'll re-post v17 with all new acks/r-b's soon, will also
link your images in the cover letter.

-- 
Best regards,
Dmitry




Re: [PATCH v2] virtio-gpu: Correct virgl_renderer_resource_get_info() error check

2024-08-09 Thread Dmitry Osipenko
On 8/9/24 12:16, Philippe Mathieu-Daudé wrote:
> Hi Dmitry,
> 
> On 29/1/24 08:39, Dmitry Osipenko wrote:
>> virgl_renderer_resource_get_info() returns errno and not -1 on error.
> 
> So basically we were ignoring all errors...
> 
> Could some errors just be safely ignored? Because apparently
> this patch now gives troubles, see:
> https://gitlab.com/qemu-project/qemu/-/issues/2490
> Can you help us there?

Hi, Philippe. Replied on the gitlab.

-- 
Best regards,
Dmitry




[PATCH v16 12/13] virtio-gpu: Register capsets dynamically

2024-06-23 Thread Dmitry Osipenko
From: Pierre-Eric Pelloux-Prayer 

virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
like Venus and DRM capsets. Register capsets dynamically to avoid that problem.

Reviewed-by: Manos Pitsidianakis 
Signed-off-by: Pierre-Eric Pelloux-Prayer 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  6 --
 hw/display/virtio-gpu-virgl.c  | 33 +
 include/hw/virtio/virtio-gpu.h |  4 +++-
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 5f27568d3ec8..20a7c316bb23 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -138,8 +138,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 }
 
 g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
-VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
-virtio_gpu_virgl_get_num_capsets(g);
+g->capset_ids = virtio_gpu_virgl_get_capsets(g);
+VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
 
 #if VIRGL_VERSION_MAJOR >= 1
 g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
@@ -171,6 +171,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 }
 
 gl->renderer_state = RS_START;
+
+g_array_unref(g->capset_ids);
 }
 
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b2f4e215a7ad..5a881c58a11d 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -622,19 +622,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 VIRTIO_GPU_FILL_CMD(info);
 
 memset(&resp, 0, sizeof(resp));
-if (info.capset_index == 0) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
-virgl_renderer_get_cap_set(resp.capset_id,
-   &resp.capset_max_version,
-   &resp.capset_max_size);
-} else if (info.capset_index == 1) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+
+if (info.capset_index < g->capset_ids->len) {
+resp.capset_id = g_array_index(g->capset_ids, uint32_t,
+   info.capset_index);
 virgl_renderer_get_cap_set(resp.capset_id,
&resp.capset_max_version,
&resp.capset_max_size);
-} else {
-resp.capset_max_version = 0;
-resp.capset_max_size = 0;
 }
 resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
 virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
@@ -1160,12 +1154,27 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t capset_id)
+{
+g_array_append_val(capset_ids, capset_id);
+}
+
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
 uint32_t capset2_max_ver, capset2_max_size;
+GArray *capset_ids;
+
+capset_ids = g_array_new(false, false, sizeof(uint32_t));
+
+/* VIRGL is always supported. */
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
+
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
   &capset2_max_ver,
   &capset2_max_size);
+if (capset2_max_ver) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
+}
 
-return capset2_max_ver ? 2 : 1;
+return capset_ids;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 775005abb337..83232f4b4bfa 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -209,6 +209,8 @@ struct VirtIOGPU {
 QTAILQ_HEAD(, VGPUDMABuf) bufs;
 VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
 } dmabuf;
+
+GArray *capset_ids;
 };
 
 struct VirtIOGPUClass {
@@ -354,6 +356,6 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.45.2




[PATCH v16 01/13] virtio-gpu: Use trace events for tracking number of in-flight fences

2024-06-23 Thread Dmitry Osipenko
Replace printf's used for tracking of in-flight fence inc/dec events
with tracing, for consistency with the rest of virtio-gpu code that
uses tracing.

Suggested-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events   | 2 ++
 hw/display/virtio-gpu-virgl.c | 2 +-
 hw/display/virtio-gpu.c   | 4 ++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index 781f8a33203b..e212710284ae 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -53,6 +53,8 @@ virtio_gpu_cmd_ctx_submit(uint32_t ctx, uint32_t size) "ctx 
0x%x, size %d"
 virtio_gpu_update_cursor(uint32_t scanout, uint32_t x, uint32_t y, const char 
*type, uint32_t res) "scanout %d, x %d, y %d, %s, res 0x%x"
 virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", 
type 0x%x"
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
+virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
+virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9f34d0e6619c..14091b191ec0 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -525,7 +525,7 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d60b1b2973af..602952a7041b 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1066,7 +1066,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 if (g->stats.max_inflight < g->inflight) {
 g->stats.max_inflight = g->inflight;
 }
-fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
+trace_virtio_gpu_inc_inflight_fences(g->inflight);
 }
 } else {
 g_free(cmd);
@@ -1086,7 +1086,7 @@ static void virtio_gpu_process_fenceq(VirtIOGPU *g)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
-- 
2.45.2




[PATCH v16 10/13] virtio-gpu: Support suspension of commands processing

2024-06-23 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events | 1 +
 hw/display/virtio-gpu.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index e212710284ae..d26d663f9638 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -55,6 +55,7 @@ virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 
0x%" PRIx64 ", type
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
 virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
 virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
+virtio_gpu_cmd_suspended(uint32_t cmd) "cmd 0x%x"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 40a9d089710c..b348805fbaee 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1054,6 +1054,12 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+trace_virtio_gpu_cmd_suspended(cmd->cmd_hdr.type);
+break;
+}
+
 QTAILQ_REMOVE(&g->cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.45.2




[PATCH v16 09/13] virtio-gpu: Add virgl resource management

2024-06-23 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b3aa444bcfa5..3ffea478e723 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
&res_iovs,
&num_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs);
 }
 virgl_renderer_resource_unref(unref.resource_id);
+
+QTAILQ_REMOVE(&g->reslist, &res->base, next);
+
+g_free(res);
 }
 
 static void virgl_cmd_context_create(VirtIOGPU *g,
-- 
2.45.2




[PATCH v16 08/13] virtio-gpu: Don't require udmabuf when blobs and virgl are enabled

2024-06-23 Thread Dmitry Osipenko
The udmabuf usage is mandatory when virgl is disabled and blobs feature
enabled in the Qemu machine configuration. If virgl and blobs are enabled,
then udmabuf requirement is optional. Since udmabuf isn't widely supported
by a popular Linux distros today, let's relax the udmabuf requirement for
blobs=on,virgl=on. Now, a full-featured virtio-gpu acceleration is
available to Qemu users without a need to have udmabuf available in the
system.

Reviewed-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 602952a7041b..40a9d089710c 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1485,6 +1485,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 
 if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
 if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
+!virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
 !virtio_gpu_have_udmabuf()) {
 error_setg(errp, "need rutabaga or udmabuf for blob resources");
 return;
-- 
2.45.2




[PATCH v16 00/13] Support blob memory and venus on qemu

2024-06-23 Thread Dmitry Osipenko
e the case while context_init is disabled.

- Enable context_init by default.

- Move virtio_gpu_virgl_resource_unmap() into
  virgl_cmd_resource_unmap_blob().

- Introduce new struct virgl_gpu_resource to store virgl specific members.

- Remove erro handling of g_new0, because glib will abort() on OOM.

- Set resource uuid as option.

- Implement optional subsection of vmstate_virtio_gpu_resource_uuid_state
  for virtio live migration.

- Use g_int_hash/g_int_equal instead of the default

- Add scanout_blob function for virtio-gpu-virgl

- Resolve the memory leak on virtio-gpu-virgl

- Remove the unstable API flags check because virglrenderer is already 1.0

- Squash the render server flag support into "Initialize Venus"

Changes from V4 (virtio gpu V4) to V5

- Inverted patch 5 and 6 because we should configure
  HAVE_VIRGL_CONTEXT_INIT firstly.

- Validate owner of memory region to avoid slowing down DMA.

- Use memory_region_init_ram_ptr() instead of
  memory_region_init_ram_device_ptr().

- Adjust sequence to allocate gpu resource before virglrender resource
  creation

- Add virtio migration handling for uuid.

- Send kernel patch to define VIRTIO_GPU_CAPSET_VENUS.
  https://lore.kernel.org/lkml/20230915105918.3763061-1-ray.hu...@amd.com/

- Add meson check to make sure unstable APIs defined from 0.9.0.

Changes from V1 to V2 (virtio gpu V4)

- Remove unused #include "hw/virtio/virtio-iommu.h"

- Add a local function, called virgl_resource_destroy(), that is used
  to release a vgpu resource on error paths and in resource_unref.

- Remove virtio_gpu_virgl_resource_unmap from
  virtio_gpu_cleanup_mapping(),
  since this function won't be called on blob resources and also because
  blob resources are unmapped via virgl_cmd_resource_unmap_blob().

- In virgl_cmd_resource_create_blob(), do proper cleanup in error paths
  and move QTAILQ_INSERT_HEAD(&g->reslist, res, next) after the resource
  has been fully initialized.

- Memory region has a different life-cycle from virtio gpu resources
  i.e. cannot be released synchronously along with the vgpu resource.
  So, here the field "region" was changed to a pointer and is allocated
  dynamically when the blob is mapped.
  Also, since the pointer can be used to indicate whether the blob
  is mapped, the explicite field "mapped" was removed.

- In virgl_cmd_resource_map_blob(), add check on the value of
  res->region, to prevent beeing called twice on the same resource.

- Add a patch to enable automatic deallocation of memory regions to resolve
  use-after-free memory corruption with a reference.


Antonio Caggiano (1):
  virtio-gpu: Support Venus context

Dmitry Osipenko (8):
  virtio-gpu: Use trace events for tracking number of in-flight fences
  virtio-gpu: Move fence_poll timer to VirtIOGPUGL
  virtio-gpu: Move print_stats timer to VirtIOGPUGL
  virtio-gpu: Handle virtio_gpu_virgl_init() failure
  virtio-gpu: Unrealize GL device
  virtio-gpu: Use pkgconfig version to decide which virgl features are
available
  virtio-gpu: Don't require udmabuf when blobs and virgl are enabled
  virtio-gpu: Support suspension of commands processing

Huang Rui (2):
  virtio-gpu: Support context-init feature with virglrenderer
  virtio-gpu: Add virgl resource management

Pierre-Eric Pelloux-Prayer (1):
  virtio-gpu: Register capsets dynamically

Robert Beckett (1):
  virtio-gpu: Handle resource blob commands

 docs/system/devices/virtio-gpu.rst |  11 +
 hw/display/trace-events|   3 +
 hw/display/virtio-gpu-gl.c |  62 ++-
 hw/display/virtio-gpu-virgl.c  | 585 +++--
 hw/display/virtio-gpu.c|  44 ++-
 include/hw/virtio/virtio-gpu.h |  32 +-
 meson.build|   5 +-
 7 files changed, 685 insertions(+), 57 deletions(-)

-- 
2.45.2




[PATCH v16 06/13] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-06-23 Thread Dmitry Osipenko
New virglrerenderer features were stabilized with release of v1.0.0.
Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
with pre-release development versions of libvirglerender. Use virglrenderer
version to decide reliably which virgl features are available.

Reviewed-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 2 +-
 meson.build   | 5 +
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index a63d1f540f04..ca6f4d6cbb58 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -171,7 +171,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
 struct virgl_renderer_resource_info info;
 void *d3d_tex2d = NULL;
 
-#ifdef HAVE_VIRGL_D3D_INFO_EXT
+#if VIRGL_VERSION_MAJOR >= 1
 struct virgl_renderer_resource_info_ext ext;
 memset(&ext, 0, sizeof(ext));
 ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
diff --git a/meson.build b/meson.build
index 97e00d6f59b8..838d08ef0f9b 100644
--- a/meson.build
+++ b/meson.build
@@ -2329,10 +2329,7 @@ config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.found()
-  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
-   cc.has_member('struct 
virgl_renderer_resource_info_ext', 'd3d_tex2d',
- prefix: '#include ',
- dependencies: virgl))
+  config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.45.2




[PATCH v16 04/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-23 Thread Dmitry Osipenko
virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
return code and don't execute virtio commands on error. Failed
virtio_gpu_virgl_init() will result in a timed out virtio commands
for a guest OS.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 30 ++
 include/hw/virtio/virtio-gpu.h | 11 +--
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index e06be60dfbfc..21a1e9a05c5d 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  struct virtio_gpu_scanout *s,
  uint32_t resource_id)
 {
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 uint32_t width, height;
 uint32_t pixels, *data;
 
+if (gl->renderer_state != RS_INITED) {
+return;
+}
+
 data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
 if (!data) {
 return;
@@ -65,13 +70,22 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, 
VirtQueue *vq)
 return;
 }
 
-if (!gl->renderer_inited) {
-virtio_gpu_virgl_init(g);
-gl->renderer_inited = true;
-}
-if (gl->renderer_reset) {
-gl->renderer_reset = false;
+switch (gl->renderer_state) {
+case RS_RESET:
 virtio_gpu_virgl_reset(g);
+/* fallthrough */
+case RS_START:
+if (virtio_gpu_virgl_init(g)) {
+gl->renderer_state = RS_INIT_FAILED;
+return;
+}
+
+gl->renderer_state = RS_INITED;
+break;
+case RS_INIT_FAILED:
+return;
+case RS_INITED:
+break;
 }
 
 cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
@@ -98,9 +112,9 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
  * GL functions must be called with the associated GL context in main
  * thread, and when the renderer is unblocked.
  */
-if (gl->renderer_inited && !gl->renderer_reset) {
+if (gl->renderer_state == RS_INITED) {
 virtio_gpu_virgl_reset_scanout(g);
-gl->renderer_reset = true;
+gl->renderer_state = RS_RESET;
 }
 }
 
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7ff989a45a5c..6e71d799e5da 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -224,11 +224,18 @@ struct VirtIOGPUClass {
  Error **errp);
 };
 
+/* VirtIOGPUGL renderer states */
+typedef enum {
+RS_START,   /* starting state */
+RS_INIT_FAILED, /* failed initialisation */
+RS_INITED,  /* initialised and working */
+RS_RESET,   /* inited and reset pending, moves to start after reset */
+} RenderState;
+
 struct VirtIOGPUGL {
 struct VirtIOGPU parent_obj;
 
-bool renderer_inited;
-bool renderer_reset;
+RenderState renderer_state;
 
 QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
-- 
2.45.2




[PATCH v16 02/13] virtio-gpu: Move fence_poll timer to VirtIOGPUGL

2024-06-23 Thread Dmitry Osipenko
Move fence_poll timer to VirtIOGPUGL for consistency with cmdq_resume_bh
that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 8 +---
 include/hw/virtio/virtio-gpu.h | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 14091b191ec0..91dce90f9176 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -594,11 +594,12 @@ static void virtio_gpu_print_stats(void *opaque)
 static void virtio_gpu_fence_poll(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 virgl_renderer_poll();
 virtio_gpu_process_cmdq(g);
 if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
-timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
+timer_mod(gl->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
 }
 }
 
@@ -626,6 +627,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 {
 int ret;
 uint32_t flags = 0;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 if (qemu_egl_display) {
@@ -645,8 +647,8 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return ret;
 }
 
-g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- virtio_gpu_fence_poll, g);
+gl->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+  virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a7a..bc69fd78a440 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
 
 uint32_t inflight;
@@ -231,6 +230,8 @@ struct VirtIOGPUGL {
 
 bool renderer_inited;
 bool renderer_reset;
+
+QEMUTimer *fence_poll;
 };
 
 struct VhostUserGPU {
-- 
2.45.2




[PATCH v16 03/13] virtio-gpu: Move print_stats timer to VirtIOGPUGL

2024-06-23 Thread Dmitry Osipenko
Move print_stats timer to VirtIOGPUGL for consistency with
cmdq_resume_bh and fence_poll that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 10 ++
 include/hw/virtio/virtio-gpu.h |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 91dce90f9176..a63d1f540f04 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -574,6 +574,7 @@ static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
 static void virtio_gpu_print_stats(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 if (g->stats.requests) {
 fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
@@ -588,7 +589,7 @@ static void virtio_gpu_print_stats(void *opaque)
 } else {
 fprintf(stderr, "stats: idle\r");
 }
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+timer_mod(gl->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 static void virtio_gpu_fence_poll(void *opaque)
@@ -651,9 +652,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
   virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
-  virtio_gpu_print_stats, g);
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 
1000);
+gl->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+   virtio_gpu_print_stats, g);
+timer_mod(gl->print_stats,
+  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 return 0;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index bc69fd78a440..7ff989a45a5c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *print_stats;
 
 uint32_t inflight;
 struct {
@@ -232,6 +231,7 @@ struct VirtIOGPUGL {
 bool renderer_reset;
 
 QEMUTimer *fence_poll;
+QEMUTimer *print_stats;
 };
 
 struct VhostUserGPU {
-- 
2.45.2




[PATCH v16 11/13] virtio-gpu: Handle resource blob commands

2024-06-23 Thread Dmitry Osipenko
From: Robert Beckett 

Support BLOB resources creation, mapping, unmapping and set-scanout by
calling the new stable virglrenderer 0.10 interface. Only enabled when
available and via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Robert Beckett  # added 
set_scanout_blob
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |   3 +
 hw/display/virtio-gpu-virgl.c  | 414 -
 hw/display/virtio-gpu.c|  18 +-
 include/hw/virtio/virtio-gpu.h |   9 +
 4 files changed, 434 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 4fe9e6a0c21c..5f27568d3ec8 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -160,6 +160,9 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
 
 if (gl->renderer_state >= RS_INITED) {
+#if VIRGL_VERSION_MAJOR >= 1
+qemu_bh_delete(gl->cmdq_resume_bh);
+#endif
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 timer_free(gl->print_stats);
 }
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 3ffea478e723..b2f4e215a7ad 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -24,6 +26,7 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -47,6 +50,145 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#if VIRGL_VERSION_MAJOR >= 1
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+bool finish_unmapping;
+};
+
+static struct virtio_gpu_virgl_hostmem_region *
+to_hostmem_region(MemoryRegion *mr)
+{
+return container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+}
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+VirtIOGPUGL *gl;
+
+vmr = to_hostmem_region(mr);
+vmr->finish_unmapping = true;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+gl = VIRTIO_GPU_GL(vmr->g);
+qemu_bh_schedule(gl->cmdq_resume_bh);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->g = g;
+
+mr = &vmr->mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(&b->hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
+ struct virtio_gpu_virgl_resource *res,
+ bool *cmd_suspended)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+int ret;
+
+if (!mr) {
+return 0;
+}
+
+vmr = to_hostmem

[PATCH v16 13/13] virtio-gpu: Support Venus context

2024-06-23 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 docs/system/devices/virtio-gpu.rst | 11 +++
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 15 +++
 include/hw/virtio/virtio-gpu.h |  3 +++
 5 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/docs/system/devices/virtio-gpu.rst 
b/docs/system/devices/virtio-gpu.rst
index cb73dd799858..b7eb0fc0e727 100644
--- a/docs/system/devices/virtio-gpu.rst
+++ b/docs/system/devices/virtio-gpu.rst
@@ -71,6 +71,17 @@ representation back to OpenGL API calls.
 .. _Gallium3D: https://www.freedesktop.org/wiki/Software/gallium/
 .. _virglrenderer: https://gitlab.freedesktop.org/virgl/virglrenderer/
 
+Translation of Vulkan API calls is supported since release of `virglrenderer`_
+v1.0.0 using `venus`_ protocol. ``Venus`` virtio-gpu capability set ("capset")
+requires host blob support (``hostmem`` and ``blob`` fields) and should
+be enabled using ``venus`` field. The ``hostmem`` field specifies the size
+of virtio-gpu host memory window. This is typically between 256M and 8G.
+
+.. parsed-literal::
+-device virtio-gpu-gl,hostmem=8G,blob=true,venus=true
+
+.. _venus: https://gitlab.freedesktop.org/virgl/venus-protocol/
+
 virtio-gpu rutabaga
 ---
 
diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 20a7c316bb23..9be452547322 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -151,6 +151,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 5a881c58a11d..eedae7357f1a 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1128,6 +1128,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#if VIRGL_VERSION_MAJOR >= 1
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs);
 if (ret != 0) {
@@ -1161,7 +1166,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1170,11 +1175,20 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  &capset2_max_ver,
-  &capset2_max_size);
-if (capset2_max_ver) {
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index a5db2256a4bb..50b5634af13f 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1507,6 +1507,21 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef VIRGL_VERSION_MAJOR
+#if VIRGL_VERSION_MAJOR >= 1
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+#endif
+}
+
 if (!virtio_gpu_base_device_realize(qdev,
 virtio_gpu_handle_ctrl_cb,
 virtio_gpu_h

[PATCH v16 07/13] virtio-gpu: Support context-init feature with virglrenderer

2024-06-23 Thread Dmitry Osipenko
From: Huang Rui 

Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
feature flags. Expose this feature and support creating virglrenderer
context with flags using context_id if libvirglrenderer is new enough.

Originally-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c|  4 
 hw/display/virtio-gpu-virgl.c | 20 ++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 0109244276fc..4fe9e6a0c21c 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -141,6 +141,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
*qdev, Error **errp)
 VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
 virtio_gpu_virgl_get_num_capsets(g);
 
+#if VIRGL_VERSION_MAJOR >= 1
+g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
+#endif
+
 virtio_gpu_device_realize(qdev, errp);
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index ca6f4d6cbb58..b3aa444bcfa5 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
 trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
 cc.debug_name);
 
-virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
-  cc.debug_name);
+if (cc.context_init) {
+if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+return;
+}
+
+#if VIRGL_VERSION_MAJOR >= 1
+virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
+ cc.context_init,
+ cc.nlen,
+ cc.debug_name);
+return;
+#endif
+}
+
+virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
 }
 
 static void virgl_cmd_context_destroy(VirtIOGPU *g,
-- 
2.45.2




[PATCH v16 05/13] virtio-gpu: Unrealize GL device

2024-06-23 Thread Dmitry Osipenko
Even though GL GPU doesn't support hotplugging today, free virgl
resources when GL device is unrealized. For consistency.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 21a1e9a05c5d..0109244276fc 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -150,6 +150,22 @@ static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
+{
+VirtIOGPU *g = VIRTIO_GPU(qdev);
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
+
+if (gl->renderer_state >= RS_INITED) {
+if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
+timer_free(gl->print_stats);
+}
+timer_free(gl->fence_poll);
+virgl_renderer_cleanup(NULL);
+}
+
+gl->renderer_state = RS_START;
+}
+
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -163,6 +179,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
void *data)
 vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
 
 vdc->realize = virtio_gpu_gl_device_realize;
+vdc->unrealize = virtio_gpu_gl_device_unrealize;
 vdc->reset = virtio_gpu_gl_reset;
 device_class_set_props(dc, virtio_gpu_gl_properties);
 }
-- 
2.45.2




Re: [PATCH v15 10/14] virtio-gpu: Support blob scanout using dmabuf fd

2024-06-23 Thread Dmitry Osipenko
On 6/23/24 08:44, Akihiko Odaki wrote:
> On 2024/06/23 6:55, Dmitry Osipenko wrote:
>> From: Robert Beckett 
>>
>> Support displaying blob resources by handling SET_SCANOUT_BLOB
>> command.
>>
>> Signed-by: Antonio Caggiano 
>> Signed-off-by: Robert Beckett 
>> Signed-off-by: Huang Rui 
>> Reviewed-by: Antonio Caggiano 
>> Signed-off-by: Dmitry Osipenko 
>> ---
>>   hw/display/virtio-gpu-virgl.c  | 109 +
>>   hw/display/virtio-gpu.c    |  12 ++--
>>   include/hw/virtio/virtio-gpu.h |   7 +++
>>   3 files changed, 122 insertions(+), 6 deletions(-)
>>
>> diff --git a/hw/display/virtio-gpu-virgl.c
>> b/hw/display/virtio-gpu-virgl.c
>> index 3ffea478e723..60befab7efc2 100644
>> --- a/hw/display/virtio-gpu-virgl.c
>> +++ b/hw/display/virtio-gpu-virgl.c
>> @@ -17,6 +17,8 @@
>>   #include "trace.h"
>>   #include "hw/virtio/virtio.h"
>>   #include "hw/virtio/virtio-gpu.h"
>> +#include "hw/virtio/virtio-gpu-bswap.h"
>> +#include "hw/virtio/virtio-gpu-pixman.h"
>>     #include "ui/egl-helpers.h"
>>   @@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU
>> *g,
>>   res->base.height = c2d.height;
>>   res->base.format = c2d.format;
>>   res->base.resource_id = c2d.resource_id;
>> +    res->base.dmabuf_fd = -1;
>>   QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
>>     args.handle = c2d.resource_id;
>> @@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU
>> *g,
>>   res->base.height = c3d.height;
>>   res->base.format = c3d.format;
>>   res->base.resource_id = c3d.resource_id;
>> +    res->base.dmabuf_fd = -1;
>>   QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
>>     args.handle = c3d.resource_id;
>> @@ -509,6 +513,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
>>   g_free(resp);
>>   }
>>   +#if VIRGL_VERSION_MAJOR >= 1
>> +static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
>> +   struct virtio_gpu_ctrl_command
>> *cmd)
>> +{
>> +    struct virtio_gpu_framebuffer fb = { 0 };
>> +    struct virgl_renderer_resource_info info;
>> +    struct virtio_gpu_virgl_resource *res;
>> +    struct virtio_gpu_set_scanout_blob ss;
>> +    uint64_t fbend;
>> +
>> +    VIRTIO_GPU_FILL_CMD(ss);
>> +    virtio_gpu_scanout_blob_bswap(&ss);
>> +    trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
>> +  ss.r.width, ss.r.height,
>> ss.r.x,
>> +  ss.r.y);
>> +
>> +    if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
>> +    qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id
>> specified %d",
>> +  __func__, ss.scanout_id);
>> +    cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
>> +    return;
>> +    }
>> +
>> +    if (ss.resource_id == 0) {
>> +    virtio_gpu_disable_scanout(g, ss.scanout_id);
>> +    return;
>> +    }
>> +
>> +    if (ss.width < 16 ||
>> +    ss.height < 16 ||
>> +    ss.r.x + ss.r.width > ss.width ||
>> +    ss.r.y + ss.r.height > ss.height) {
>> +    qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds
>> for"
>> +  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
>> +  __func__, ss.scanout_id, ss.resource_id,
>> +  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
>> +  ss.width, ss.height);
>> +    cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
>> +    return;
>> +    }
>> +
>> +    res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
>> +    if (!res) {
>> +    qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist
>> %d\n",
>> +  __func__, ss.resource_id);
>> +    cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
>> +    return;
>> +    }
>> +    if (virgl_renderer_resource_get_info(ss.resource_id, &info)) {
>> +    qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have
>> info %d\n",
>> +  __func__, ss.resource_id);
>> +    cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
>> +    return;
>> +    }
>> +    if (res->base.dmabuf_fd < 0) {
>> +    res->base.dmabuf_fd = info.fd;
> 
> Just in case you missed my previous email:
>> res->base.dmabuf_fd is conditionally assigned but
>> virgl_renderer_resource_get_info() is called unconditionally, which is
>> inconsistent.
> 
>> The relevant code is better to be moved into
>> virgl_cmd_resource_create_blob() for consistenty with
>> virtio_gpu_resource_create_blob().

Right, I squashed this change into patch #12 instead of #10 by mistake.
Will fix it shortly, thanks for the review!

-- 
Best regards,
Dmitry




[PATCH v15 00/14] Support blob memory and venus on qemu

2024-06-22 Thread Dmitry Osipenko
d of the default

- Add scanout_blob function for virtio-gpu-virgl

- Resolve the memory leak on virtio-gpu-virgl

- Remove the unstable API flags check because virglrenderer is already 1.0

- Squash the render server flag support into "Initialize Venus"

Changes from V4 (virtio gpu V4) to V5

- Inverted patch 5 and 6 because we should configure
  HAVE_VIRGL_CONTEXT_INIT firstly.

- Validate owner of memory region to avoid slowing down DMA.

- Use memory_region_init_ram_ptr() instead of
  memory_region_init_ram_device_ptr().

- Adjust sequence to allocate gpu resource before virglrender resource
  creation

- Add virtio migration handling for uuid.

- Send kernel patch to define VIRTIO_GPU_CAPSET_VENUS.
  https://lore.kernel.org/lkml/20230915105918.3763061-1-ray.hu...@amd.com/

- Add meson check to make sure unstable APIs defined from 0.9.0.

Changes from V1 to V2 (virtio gpu V4)

- Remove unused #include "hw/virtio/virtio-iommu.h"

- Add a local function, called virgl_resource_destroy(), that is used
  to release a vgpu resource on error paths and in resource_unref.

- Remove virtio_gpu_virgl_resource_unmap from
  virtio_gpu_cleanup_mapping(),
  since this function won't be called on blob resources and also because
  blob resources are unmapped via virgl_cmd_resource_unmap_blob().

- In virgl_cmd_resource_create_blob(), do proper cleanup in error paths
  and move QTAILQ_INSERT_HEAD(&g->reslist, res, next) after the resource
  has been fully initialized.

- Memory region has a different life-cycle from virtio gpu resources
  i.e. cannot be released synchronously along with the vgpu resource.
  So, here the field "region" was changed to a pointer and is allocated
  dynamically when the blob is mapped.
  Also, since the pointer can be used to indicate whether the blob
  is mapped, the explicite field "mapped" was removed.

- In virgl_cmd_resource_map_blob(), add check on the value of
  res->region, to prevent beeing called twice on the same resource.

- Add a patch to enable automatic deallocation of memory regions to resolve
  use-after-free memory corruption with a reference.


Antonio Caggiano (2):
  virtio-gpu: Handle resource blob commands
  virtio-gpu: Support Venus context

Dmitry Osipenko (8):
  virtio-gpu: Use trace events for tracking number of in-flight fences
  virtio-gpu: Move fence_poll timer to VirtIOGPUGL
  virtio-gpu: Move print_stats timer to VirtIOGPUGL
  virtio-gpu: Handle virtio_gpu_virgl_init() failure
  virtio-gpu: Unrealize GL device
  virtio-gpu: Use pkgconfig version to decide which virgl features are
available
  virtio-gpu: Don't require udmabuf when blobs and virgl are enabled
  virtio-gpu: Support suspension of commands processing

Huang Rui (2):
  virtio-gpu: Support context-init feature with virglrenderer
  virtio-gpu: Add virgl resource management

Pierre-Eric Pelloux-Prayer (1):
  virtio-gpu: Register capsets dynamically

Robert Beckett (1):
  virtio-gpu: Support blob scanout using dmabuf fd

 hw/display/trace-events|   3 +
 hw/display/virtio-gpu-gl.c |  62 +++-
 hw/display/virtio-gpu-virgl.c  | 592 +++--
 hw/display/virtio-gpu.c|  44 ++-
 include/hw/virtio/virtio-gpu.h |  32 +-
 meson.build|   5 +-
 6 files changed, 681 insertions(+), 57 deletions(-)

-- 
2.45.2




[PATCH v15 01/14] virtio-gpu: Use trace events for tracking number of in-flight fences

2024-06-22 Thread Dmitry Osipenko
Replace printf's used for tracking of in-flight fence inc/dec events
with tracing, for consistency with the rest of virtio-gpu code that
uses tracing.

Suggested-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events   | 2 ++
 hw/display/virtio-gpu-virgl.c | 2 +-
 hw/display/virtio-gpu.c   | 4 ++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index 781f8a33203b..e212710284ae 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -53,6 +53,8 @@ virtio_gpu_cmd_ctx_submit(uint32_t ctx, uint32_t size) "ctx 
0x%x, size %d"
 virtio_gpu_update_cursor(uint32_t scanout, uint32_t x, uint32_t y, const char 
*type, uint32_t res) "scanout %d, x %d, y %d, %s, res 0x%x"
 virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", 
type 0x%x"
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
+virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
+virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9f34d0e6619c..14091b191ec0 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -525,7 +525,7 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d60b1b2973af..602952a7041b 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1066,7 +1066,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 if (g->stats.max_inflight < g->inflight) {
 g->stats.max_inflight = g->inflight;
 }
-fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
+trace_virtio_gpu_inc_inflight_fences(g->inflight);
 }
 } else {
 g_free(cmd);
@@ -1086,7 +1086,7 @@ static void virtio_gpu_process_fenceq(VirtIOGPU *g)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
-- 
2.45.2




[PATCH v15 10/14] virtio-gpu: Support blob scanout using dmabuf fd

2024-06-22 Thread Dmitry Osipenko
From: Robert Beckett 

Support displaying blob resources by handling SET_SCANOUT_BLOB
command.

Signed-by: Antonio Caggiano 
Signed-off-by: Robert Beckett 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 109 +
 hw/display/virtio-gpu.c|  12 ++--
 include/hw/virtio/virtio-gpu.h |   7 +++
 3 files changed, 122 insertions(+), 6 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 3ffea478e723..60befab7efc2 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 res->base.height = c2d.height;
 res->base.format = c2d.format;
 res->base.resource_id = c2d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c2d.resource_id;
@@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 res->base.height = c3d.height;
 res->base.format = c3d.format;
 res->base.resource_id = c3d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c3d.resource_id;
@@ -509,6 +513,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
 g_free(resp);
 }
 
+#if VIRGL_VERSION_MAJOR >= 1
+static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
+   struct virtio_gpu_ctrl_command *cmd)
+{
+struct virtio_gpu_framebuffer fb = { 0 };
+struct virgl_renderer_resource_info info;
+struct virtio_gpu_virgl_resource *res;
+struct virtio_gpu_set_scanout_blob ss;
+uint64_t fbend;
+
+VIRTIO_GPU_FILL_CMD(ss);
+virtio_gpu_scanout_blob_bswap(&ss);
+trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
+  ss.r.width, ss.r.height, ss.r.x,
+  ss.r.y);
+
+if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+  __func__, ss.scanout_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+return;
+}
+
+if (ss.resource_id == 0) {
+virtio_gpu_disable_scanout(g, ss.scanout_id);
+return;
+}
+
+if (ss.width < 16 ||
+ss.height < 16 ||
+ss.r.x + ss.r.width > ss.width ||
+ss.r.y + ss.r.height > ss.height) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
+  __func__, ss.scanout_id, ss.resource_id,
+  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
+  ss.width, ss.height);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (virgl_renderer_resource_get_info(ss.resource_id, &info)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have info %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (res->base.dmabuf_fd < 0) {
+res->base.dmabuf_fd = info.fd;
+}
+if (res->base.dmabuf_fd < 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource not backed by dmabuf 
%d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+fb.format = virtio_gpu_get_pixman_format(ss.format);
+if (!fb.format) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: pixel format not supported %d\n",
+  __func__, ss.format);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+fb.width = ss.width;
+fb.height = ss.height;
+fb.stride = ss.strides[0];
+fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
+
+fbend = fb.offset;
+fbend += fb.stride * (ss.r.height - 1);
+fbend += fb.bytes_pp * ss.r.width;
+if (fbend > res-

[PATCH v15 13/14] virtio-gpu: Register capsets dynamically

2024-06-22 Thread Dmitry Osipenko
From: Pierre-Eric Pelloux-Prayer 

virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
like Venus and DRM capsets. Register capsets dynamically to avoid that problem.

Reviewed-by: Manos Pitsidianakis 
Signed-off-by: Pierre-Eric Pelloux-Prayer 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  6 --
 hw/display/virtio-gpu-virgl.c  | 33 +
 include/hw/virtio/virtio-gpu.h |  4 +++-
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 5f27568d3ec8..20a7c316bb23 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -138,8 +138,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 }
 
 g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
-VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
-virtio_gpu_virgl_get_num_capsets(g);
+g->capset_ids = virtio_gpu_virgl_get_capsets(g);
+VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
 
 #if VIRGL_VERSION_MAJOR >= 1
 g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
@@ -171,6 +171,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 }
 
 gl->renderer_state = RS_START;
+
+g_array_unref(g->capset_ids);
 }
 
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index f6cb4fe5b28e..58693dfa2afa 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -629,19 +629,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 VIRTIO_GPU_FILL_CMD(info);
 
 memset(&resp, 0, sizeof(resp));
-if (info.capset_index == 0) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
-virgl_renderer_get_cap_set(resp.capset_id,
-   &resp.capset_max_version,
-   &resp.capset_max_size);
-} else if (info.capset_index == 1) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+
+if (info.capset_index < g->capset_ids->len) {
+resp.capset_id = g_array_index(g->capset_ids, uint32_t,
+   info.capset_index);
 virgl_renderer_get_cap_set(resp.capset_id,
&resp.capset_max_version,
&resp.capset_max_size);
-} else {
-resp.capset_max_version = 0;
-resp.capset_max_size = 0;
 }
 resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
 virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
@@ -1167,12 +1161,27 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t capset_id)
+{
+g_array_append_val(capset_ids, capset_id);
+}
+
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
 uint32_t capset2_max_ver, capset2_max_size;
+GArray *capset_ids;
+
+capset_ids = g_array_new(false, false, sizeof(uint32_t));
+
+/* VIRGL is always supported. */
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
+
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
   &capset2_max_ver,
   &capset2_max_size);
+if (capset2_max_ver) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
+}
 
-return capset2_max_ver ? 2 : 1;
+return capset_ids;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 775005abb337..83232f4b4bfa 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -209,6 +209,8 @@ struct VirtIOGPU {
 QTAILQ_HEAD(, VGPUDMABuf) bufs;
 VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
 } dmabuf;
+
+GArray *capset_ids;
 };
 
 struct VirtIOGPUClass {
@@ -354,6 +356,6 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.45.2




[PATCH v15 07/14] virtio-gpu: Support context-init feature with virglrenderer

2024-06-22 Thread Dmitry Osipenko
From: Huang Rui 

Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
feature flags. Expose this feature and support creating virglrenderer
context with flags using context_id if libvirglrenderer is new enough.

Originally-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c|  4 
 hw/display/virtio-gpu-virgl.c | 20 ++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 0109244276fc..4fe9e6a0c21c 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -141,6 +141,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
*qdev, Error **errp)
 VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
 virtio_gpu_virgl_get_num_capsets(g);
 
+#if VIRGL_VERSION_MAJOR >= 1
+g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
+#endif
+
 virtio_gpu_device_realize(qdev, errp);
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index ca6f4d6cbb58..b3aa444bcfa5 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
 trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
 cc.debug_name);
 
-virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
-  cc.debug_name);
+if (cc.context_init) {
+if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+return;
+}
+
+#if VIRGL_VERSION_MAJOR >= 1
+virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
+ cc.context_init,
+ cc.nlen,
+ cc.debug_name);
+return;
+#endif
+}
+
+virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
 }
 
 static void virgl_cmd_context_destroy(VirtIOGPU *g,
-- 
2.45.2




[PATCH v15 06/14] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-06-22 Thread Dmitry Osipenko
New virglrerenderer features were stabilized with release of v1.0.0.
Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
with pre-release development versions of libvirglerender. Use virglrenderer
version to decide reliably which virgl features are available.

Reviewed-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 2 +-
 meson.build   | 5 +
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index a63d1f540f04..ca6f4d6cbb58 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -171,7 +171,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
 struct virgl_renderer_resource_info info;
 void *d3d_tex2d = NULL;
 
-#ifdef HAVE_VIRGL_D3D_INFO_EXT
+#if VIRGL_VERSION_MAJOR >= 1
 struct virgl_renderer_resource_info_ext ext;
 memset(&ext, 0, sizeof(ext));
 ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
diff --git a/meson.build b/meson.build
index 97e00d6f59b8..838d08ef0f9b 100644
--- a/meson.build
+++ b/meson.build
@@ -2329,10 +2329,7 @@ config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.found()
-  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
-   cc.has_member('struct 
virgl_renderer_resource_info_ext', 'd3d_tex2d',
- prefix: '#include ',
- dependencies: virgl))
+  config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.45.2




[PATCH v15 09/14] virtio-gpu: Add virgl resource management

2024-06-22 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b3aa444bcfa5..3ffea478e723 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
&res_iovs,
&num_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs);
 }
 virgl_renderer_resource_unref(unref.resource_id);
+
+QTAILQ_REMOVE(&g->reslist, &res->base, next);
+
+g_free(res);
 }
 
 static void virgl_cmd_context_create(VirtIOGPU *g,
-- 
2.45.2




[PATCH v15 02/14] virtio-gpu: Move fence_poll timer to VirtIOGPUGL

2024-06-22 Thread Dmitry Osipenko
Move fence_poll timer to VirtIOGPUGL for consistency with cmdq_resume_bh
that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 8 +---
 include/hw/virtio/virtio-gpu.h | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 14091b191ec0..91dce90f9176 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -594,11 +594,12 @@ static void virtio_gpu_print_stats(void *opaque)
 static void virtio_gpu_fence_poll(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 virgl_renderer_poll();
 virtio_gpu_process_cmdq(g);
 if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
-timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
+timer_mod(gl->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
 }
 }
 
@@ -626,6 +627,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 {
 int ret;
 uint32_t flags = 0;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 if (qemu_egl_display) {
@@ -645,8 +647,8 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return ret;
 }
 
-g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- virtio_gpu_fence_poll, g);
+gl->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+  virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a7a..bc69fd78a440 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
 
 uint32_t inflight;
@@ -231,6 +230,8 @@ struct VirtIOGPUGL {
 
 bool renderer_inited;
 bool renderer_reset;
+
+QEMUTimer *fence_poll;
 };
 
 struct VhostUserGPU {
-- 
2.45.2




[PATCH v15 04/14] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-22 Thread Dmitry Osipenko
virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
return code and don't execute virtio commands on error. Failed
virtio_gpu_virgl_init() will result in a timed out virtio commands
for a guest OS.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 30 ++
 include/hw/virtio/virtio-gpu.h | 11 +--
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index e06be60dfbfc..21a1e9a05c5d 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  struct virtio_gpu_scanout *s,
  uint32_t resource_id)
 {
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 uint32_t width, height;
 uint32_t pixels, *data;
 
+if (gl->renderer_state != RS_INITED) {
+return;
+}
+
 data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
 if (!data) {
 return;
@@ -65,13 +70,22 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, 
VirtQueue *vq)
 return;
 }
 
-if (!gl->renderer_inited) {
-virtio_gpu_virgl_init(g);
-gl->renderer_inited = true;
-}
-if (gl->renderer_reset) {
-gl->renderer_reset = false;
+switch (gl->renderer_state) {
+case RS_RESET:
 virtio_gpu_virgl_reset(g);
+/* fallthrough */
+case RS_START:
+if (virtio_gpu_virgl_init(g)) {
+gl->renderer_state = RS_INIT_FAILED;
+return;
+}
+
+gl->renderer_state = RS_INITED;
+break;
+case RS_INIT_FAILED:
+return;
+case RS_INITED:
+break;
 }
 
 cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
@@ -98,9 +112,9 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
  * GL functions must be called with the associated GL context in main
  * thread, and when the renderer is unblocked.
  */
-if (gl->renderer_inited && !gl->renderer_reset) {
+if (gl->renderer_state == RS_INITED) {
 virtio_gpu_virgl_reset_scanout(g);
-gl->renderer_reset = true;
+gl->renderer_state = RS_RESET;
 }
 }
 
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7ff989a45a5c..6e71d799e5da 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -224,11 +224,18 @@ struct VirtIOGPUClass {
  Error **errp);
 };
 
+/* VirtIOGPUGL renderer states */
+typedef enum {
+RS_START,   /* starting state */
+RS_INIT_FAILED, /* failed initialisation */
+RS_INITED,  /* initialised and working */
+RS_RESET,   /* inited and reset pending, moves to start after reset */
+} RenderState;
+
 struct VirtIOGPUGL {
 struct VirtIOGPU parent_obj;
 
-bool renderer_inited;
-bool renderer_reset;
+RenderState renderer_state;
 
 QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
-- 
2.45.2




[PATCH v15 11/14] virtio-gpu: Support suspension of commands processing

2024-06-22 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events | 1 +
 hw/display/virtio-gpu.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index e212710284ae..d26d663f9638 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -55,6 +55,7 @@ virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 
0x%" PRIx64 ", type
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
 virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
 virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
+virtio_gpu_cmd_suspended(uint32_t cmd) "cmd 0x%x"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 95091c4b7924..1c6e97fb6931 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1054,6 +1054,12 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+trace_virtio_gpu_cmd_suspended(cmd->cmd_hdr.type);
+break;
+}
+
 QTAILQ_REMOVE(&g->cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.45.2




[PATCH v15 05/14] virtio-gpu: Unrealize GL device

2024-06-22 Thread Dmitry Osipenko
Even though GL GPU doesn't support hotplugging today, free virgl
resources when GL device is unrealized. For consistency.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 21a1e9a05c5d..0109244276fc 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -150,6 +150,22 @@ static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
+{
+VirtIOGPU *g = VIRTIO_GPU(qdev);
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
+
+if (gl->renderer_state >= RS_INITED) {
+if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
+timer_free(gl->print_stats);
+}
+timer_free(gl->fence_poll);
+virgl_renderer_cleanup(NULL);
+}
+
+gl->renderer_state = RS_START;
+}
+
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -163,6 +179,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
void *data)
 vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
 
 vdc->realize = virtio_gpu_gl_device_realize;
+vdc->unrealize = virtio_gpu_gl_device_unrealize;
 vdc->reset = virtio_gpu_gl_reset;
 device_class_set_props(dc, virtio_gpu_gl_properties);
 }
-- 
2.45.2




[PATCH v15 14/14] virtio-gpu: Support Venus context

2024-06-22 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 15 +++
 include/hw/virtio/virtio-gpu.h |  3 +++
 4 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 20a7c316bb23..9be452547322 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -151,6 +151,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 58693dfa2afa..08b0e7e49337 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1135,6 +1135,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#if VIRGL_VERSION_MAJOR >= 1
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs);
 if (ret != 0) {
@@ -1168,7 +1173,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1177,11 +1182,20 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  &capset2_max_ver,
-  &capset2_max_size);
-if (capset2_max_ver) {
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index a5db2256a4bb..50b5634af13f 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1507,6 +1507,21 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef VIRGL_VERSION_MAJOR
+#if VIRGL_VERSION_MAJOR >= 1
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+#endif
+}
+
 if (!virtio_gpu_base_device_realize(qdev,
 virtio_gpu_handle_ctrl_cb,
 virtio_gpu_handle_cursor_cb,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 83232f4b4bfa..230fa0c4ee0a 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -99,6 +99,7 @@ enum virtio_gpu_base_conf_flags {
 VIRTIO_GPU_FLAG_BLOB_ENABLED,
 VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED,
 VIRTIO_GPU_FLAG_RUTABAGA_ENABLED,
+VIRTIO_GPU_FLAG_VENUS_ENABLED,
 };
 
 #define virtio_gpu_virgl_enabled(_cfg) \
@@ -117,6 +118,8 @@ enum virtio_gpu_base_conf_flags {
 (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED))
 #define virtio_gpu_hostmem_enabled(_cfg) \
 (_cfg.hostmem > 0)
+#define virtio_gpu_venus_enabled(_cfg) \
+(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VENUS_ENABLED))
 
 struct virtio_gpu_base_conf {
 uint32_t max_outputs;
-- 
2.45.2




[PATCH v15 12/14] virtio-gpu: Handle resource blob commands

2024-06-22 Thread Dmitry Osipenko
From: Antonio Caggiano 

Support BLOB resources creation, mapping and unmapping by calling the
new stable virglrenderer 0.10 interface. Only enabled when available and
via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |   3 +
 hw/display/virtio-gpu-virgl.c  | 334 +++--
 hw/display/virtio-gpu.c|   6 +-
 include/hw/virtio/virtio-gpu.h |   2 +
 4 files changed, 330 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 4fe9e6a0c21c..5f27568d3ec8 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -160,6 +160,9 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
 
 if (gl->renderer_state >= RS_INITED) {
+#if VIRGL_VERSION_MAJOR >= 1
+qemu_bh_delete(gl->cmdq_resume_bh);
+#endif
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 timer_free(gl->print_stats);
 }
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 60befab7efc2..f6cb4fe5b28e 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -26,6 +26,7 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -49,6 +50,152 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#if VIRGL_VERSION_MAJOR >= 1
+typedef enum {
+HOSTMEM_MR_UNMAPPING,
+HOSTMEM_MR_FINISH_UNMAPPING,
+} HostmemMRState;
+
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+HostmemMRState state;
+};
+
+static struct virtio_gpu_virgl_hostmem_region *
+to_hostmem_region(MemoryRegion *mr)
+{
+return container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+}
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+VirtIOGPUGL *gl;
+
+vmr = to_hostmem_region(mr);
+vmr->state = HOSTMEM_MR_FINISH_UNMAPPING;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+gl = VIRTIO_GPU_GL(vmr->g);
+qemu_bh_schedule(gl->cmdq_resume_bh);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->g = g;
+
+mr = &vmr->mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(&b->hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
+ struct virtio_gpu_virgl_resource *res,
+ bool *cmd_suspended)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+int ret;
+
+if (!mr) {
+return 0;
+}
+
+vmr = to_hostmem_region(res->mr);
+
+/*
+ * Perform async unmapping in 3 steps:
+ *
+ * 1. Begin async unmapping with memory_region_del_subregion()
+ *and suspend/block cmd processing.
+ * 2. Wait for res->mr to be f

[PATCH v15 08/14] virtio-gpu: Don't require udmabuf when blobs and virgl are enabled

2024-06-22 Thread Dmitry Osipenko
The udmabuf usage is mandatory when virgl is disabled and blobs feature
enabled in the Qemu machine configuration. If virgl and blobs are enabled,
then udmabuf requirement is optional. Since udmabuf isn't widely supported
by a popular Linux distros today, let's relax the udmabuf requirement for
blobs=on,virgl=on. Now, a full-featured virtio-gpu acceleration is
available to Qemu users without a need to have udmabuf available in the
system.

Reviewed-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 602952a7041b..40a9d089710c 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1485,6 +1485,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 
 if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
 if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
+!virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
 !virtio_gpu_have_udmabuf()) {
 error_setg(errp, "need rutabaga or udmabuf for blob resources");
 return;
-- 
2.45.2




[PATCH v15 03/14] virtio-gpu: Move print_stats timer to VirtIOGPUGL

2024-06-22 Thread Dmitry Osipenko
Move print_stats timer to VirtIOGPUGL for consistency with
cmdq_resume_bh and fence_poll that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 10 ++
 include/hw/virtio/virtio-gpu.h |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 91dce90f9176..a63d1f540f04 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -574,6 +574,7 @@ static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
 static void virtio_gpu_print_stats(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 if (g->stats.requests) {
 fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
@@ -588,7 +589,7 @@ static void virtio_gpu_print_stats(void *opaque)
 } else {
 fprintf(stderr, "stats: idle\r");
 }
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+timer_mod(gl->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 static void virtio_gpu_fence_poll(void *opaque)
@@ -651,9 +652,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
   virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
-  virtio_gpu_print_stats, g);
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 
1000);
+gl->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+   virtio_gpu_print_stats, g);
+timer_mod(gl->print_stats,
+  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 return 0;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index bc69fd78a440..7ff989a45a5c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *print_stats;
 
 uint32_t inflight;
 struct {
@@ -232,6 +231,7 @@ struct VirtIOGPUGL {
 bool renderer_reset;
 
 QEMUTimer *fence_poll;
+QEMUTimer *print_stats;
 };
 
 struct VhostUserGPU {
-- 
2.45.2




Re: [PATCH v14 00/14] Support blob memory and venus on qemu

2024-06-21 Thread Dmitry Osipenko
On 6/21/24 11:59, Alex Bennée wrote:
> Dmitry Osipenko  writes:
> 
>> On 6/19/24 20:37, Alex Bennée wrote:
>>> So I've been experimenting with Aarch64 TCG with an Intel backend like
>>> this:
>>>
>>> ./qemu-system-aarch64 \
>>>-M virt -cpu cortex-a76 \
>>>-device virtio-net-pci,netdev=unet \
>>>-netdev user,id=unet,hostfwd=tcp::-:22 \
>>>-m 8192 \
>>>-object memory-backend-memfd,id=mem,size=8G,share=on \
>>>-serial mon:stdio \
>>>-kernel 
>>> ~/lsrc/linux.git/builds/arm64.initramfs/arch/arm64/boot/Image \
>>>-append "console=ttyAMA0" \
>>>-device qemu-xhci -device usb-kbd -device usb-tablet \
>>>-device virtio-gpu-gl-pci,blob=true,venus=true,hostmem=4G \
>>>-display sdl,gl=on -d 
>>> plugin,guest_errors,trace:virtio_gpu_cmd_res_create_blob,trace:virtio_gpu_cmd_res_back_\*,trace:virtio_gpu_cmd_res_xfer_toh_3d,trace:virtio_gpu_cmd_res_xfer_fromh_3d,trace:address_space_map
>>>  
>>>
>>> And I've noticed a couple of things. First trying to launch vkmark to
>>> run a KMS mode test fails with:
>>>
>> ...
>>>   virgl_render_server[1875931]: vkr: failed to import resource: invalid 
>>> res_id 5
>>>   virgl_render_server[1875931]: vkr: vkAllocateMemory resulted in CS error 
>>>   virgl_render_server[1875931]: vkr: ring_submit_cmd: vn_dispatch_command 
>>> failed
>>>
>>> More interestingly when shutting stuff down we see weirdness like:
>>>
>>>   address_space_map as:0x561b48ec48c0 addr 0x1008ac4b0:18 write:1 attrs:0x1 
>>> 
>>>
>>>   virgl_render_server[1875931]: vkr: destroying context 3 (vkmark) with a 
>>> valid instance  
>>>  
>>>   virgl_render_server[1875931]: vkr: destroying device with valid objects   
>>> 
>>>
>>>   vkr_context_remove_object: -7438602987017907480   
>>> 
>>>
>>>   vkr_context_remove_object: 7  
>>> 
>>>
>>>   vkr_context_remove_object: 5   
>>>
>>> which indicates something has gone very wrong. I'm not super familiar
>>> with the memory allocation patterns but should stuff that is done as
>>> virtio_gpu_cmd_res_back_attach() be find-able in the list of resources?
>>
>> This is expected to fail. Vkmark creates shmem virgl GBM FB BO on guest
>> that isn't exportable on host. AFAICT, more code changes should be
>> needed to support this case.
> 
> There are a lot of acronyms there. If this is pure guest memory why
> isn't it exportable to the host? Or should the underlying mesa library
> be making sure the allocation happens from the shared region?
> 
> Is vkmark particularly special here?

Actually, you could get it to work to a some degree if you'll compile
virglrenderer with -Dminigbm_allocation=true. On host use GTK/Wayland
display.

Vkmark isn't special. It's virglrenderer that has a room for
improvement. ChromeOS doesn't use KMS in VMs, proper KMS support was
never a priority for Venus.

>> Note that "destroying device with valid objects" msg is fine, won't hurt
>> to silence it in Venus to avoid confusion. It will happen every time
>> guest application is closed without explicitly releasing every VK
>> object.
> 
> I was more concerned with:
> 
>>>   vkr_context_remove_object: -7438602987017907480   
>>> 
>>>
> 
> which looks like a corruption of the object ids (or maybe an offby one)

At first this appeared to be a valid value, otherwise venus should've
crashed Qemu with a debug-assert if ID was invalid. But I never see such
odd IDs with my testing.

>>> I tried running under RR to further debug but weirdly I can't get
>>> working graphics with that. I did try running under threadsan which
>>> complained about a 

Re: [PATCH v14 00/14] Support blob memory and venus on qemu

2024-06-20 Thread Dmitry Osipenko
On 6/19/24 20:37, Alex Bennée wrote:
> So I've been experimenting with Aarch64 TCG with an Intel backend like
> this:
> 
> ./qemu-system-aarch64 \
>-M virt -cpu cortex-a76 \
>-device virtio-net-pci,netdev=unet \
>-netdev user,id=unet,hostfwd=tcp::-:22 \
>-m 8192 \
>-object memory-backend-memfd,id=mem,size=8G,share=on \
>-serial mon:stdio \
>-kernel 
> ~/lsrc/linux.git/builds/arm64.initramfs/arch/arm64/boot/Image \
>-append "console=ttyAMA0" \
>-device qemu-xhci -device usb-kbd -device usb-tablet \
>-device virtio-gpu-gl-pci,blob=true,venus=true,hostmem=4G \
>-display sdl,gl=on -d 
> plugin,guest_errors,trace:virtio_gpu_cmd_res_create_blob,trace:virtio_gpu_cmd_res_back_\*,trace:virtio_gpu_cmd_res_xfer_toh_3d,trace:virtio_gpu_cmd_res_xfer_fromh_3d,trace:address_space_map
>  
> 
> And I've noticed a couple of things. First trying to launch vkmark to
> run a KMS mode test fails with:
> 
...
>   virgl_render_server[1875931]: vkr: failed to import resource: invalid 
> res_id 5
>   virgl_render_server[1875931]: vkr: vkAllocateMemory resulted in CS error 
>   virgl_render_server[1875931]: vkr: ring_submit_cmd: vn_dispatch_command 
> failed
> 
> More interestingly when shutting stuff down we see weirdness like:
> 
>   address_space_map as:0x561b48ec48c0 addr 0x1008ac4b0:18 write:1 attrs:0x1   
>   
>
>   virgl_render_server[1875931]: vkr: destroying context 3 (vkmark) with a 
> valid instance
>
>   virgl_render_server[1875931]: vkr: destroying device with valid objects 
>   
>
>   vkr_context_remove_object: -7438602987017907480 
>   
>
>   vkr_context_remove_object: 7
>   
>
>   vkr_context_remove_object: 5   
> 
> which indicates something has gone very wrong. I'm not super familiar
> with the memory allocation patterns but should stuff that is done as
> virtio_gpu_cmd_res_back_attach() be find-able in the list of resources?

This is expected to fail. Vkmark creates shmem virgl GBM FB BO on guest
that isn't exportable on host. AFAICT, more code changes should be
needed to support this case.

Note that "destroying device with valid objects" msg is fine, won't hurt
to silence it in Venus to avoid confusion. It will happen every time
guest application is closed without explicitly releasing every VK object.

> I tried running under RR to further debug but weirdly I can't get
> working graphics with that. I did try running under threadsan which
> complained about a potential data race:
> 
>   vkr_context_add_object: 1 -> 0x7b2c0288
>   vkr_context_add_object: 2 -> 0x7b2c0270
>   vkr_context_add_object: 3 -> 0x7b387f28
>   vkr_context_add_object: 4 -> 0x7b387fa0
>   vkr_context_add_object: 5 -> 0x7b48000103f8
>   vkr_context_add_object: 6 -> 0x7b48000104a0
>   vkr_context_add_object: 7 -> 0x7b4800010440
>   virtio_gpu_cmd_res_back_attach res 0x5
>   virtio_gpu_cmd_res_back_attach res 0x6
>   vkr_context_add_object: 8 -> 0x7b48000103e0
>   virgl_render_server[1751430]: vkr: failed to import resource: invalid 
> res_id 5
>   virgl_render_server[1751430]: vkr: vkAllocateMemory resulted in CS error
>   virgl_render_server[1751430]: vkr: ring_submit_cmd: vn_dispatch_command 
> failed
>   ==
>   WARNING: ThreadSanitizer: data race (pid=1751256)
> Read of size 8 at 0x7f7fa0ea9138 by main thread (mutexes: write M0):
>   #0 memcpy  (qemu-system-aarch64+0x41fede) (BuildId: 
> 0bab171e77cb6782341ee3407e44af7267974025)
..
>   ==
>   SUMMARY: ThreadSanitizer: data race 
> (/home/alex/lsrc/qemu.git/builds/system.threadsan/qemu-system-aarch64+0x41fede)
>  (BuildId: 0bab171e77cb6782341ee3407e44af7267974025) in __interceptor_memcpy
> 
> This could be a false positive or it could be a race between the guest
> kernel clearing memory while we are still doing
> virtio_gpu_ctrl_response.
> 
> What do you think?

The memcpy warning looks a bit suspicion, but likely is harmless. I
don't see such warning with TSAN and x86 VM.

-- 
Best regards,
Dmitry




Re: [PATCH v14 12/14] virtio-gpu: Handle resource blob commands

2024-06-19 Thread Dmitry Osipenko
16.06.2024 12:23, Akihiko Odaki пишет:
...
>>   #endif
>>   +#if VIRGL_VERSION_MAJOR >= 1
>> +typedef enum {
>> +    HOSTMEM_MR_MAPPED,
> 
> HOSTMEM_MR_MAPPED is no longer used.

Good catch

-- 
Best regards,
Dmitry




Re: [PATCH v14 12/14] virtio-gpu: Handle resource blob commands

2024-06-19 Thread Dmitry Osipenko
19.06.2024 18:27, Alex Bennée пишет:
> Dmitry Osipenko  writes:
> 
>> From: Antonio Caggiano 
>>
>> Support BLOB resources creation, mapping and unmapping by calling the
>> new stable virglrenderer 0.10 interface. Only enabled when available and
>> via the blob config. E.g. -device virtio-vga-gl,blob=true
>>
> 
>>  
>>  #if VIRGL_VERSION_MAJOR >= 1
>> +static void virgl_cmd_resource_create_blob(VirtIOGPU *g,
>> +   struct virtio_gpu_ctrl_command 
>> *cmd)
>> +{
>> +struct virgl_renderer_resource_create_blob_args virgl_args = { 0 };
>> +g_autofree struct virtio_gpu_virgl_resource *res;
> 
> Newer compilers rightly complain that g_free may be called on an
> uninitialised value (if we early return). Setting to NULL should be
> enough here.

Good catch! GCC 13 doesn't detect it

-- 
Best regards,
Dmitry




[PATCH v14 01/14] virtio-gpu: Use trace events for tracking number of in-flight fences

2024-06-15 Thread Dmitry Osipenko
Replace printf's used for tracking of in-flight fence inc/dec events
with tracing, for consistency with the rest of virtio-gpu code that
uses tracing.

Suggested-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events   | 2 ++
 hw/display/virtio-gpu-virgl.c | 2 +-
 hw/display/virtio-gpu.c   | 4 ++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index 781f8a33203b..e212710284ae 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -53,6 +53,8 @@ virtio_gpu_cmd_ctx_submit(uint32_t ctx, uint32_t size) "ctx 
0x%x, size %d"
 virtio_gpu_update_cursor(uint32_t scanout, uint32_t x, uint32_t y, const char 
*type, uint32_t res) "scanout %d, x %d, y %d, %s, res 0x%x"
 virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", 
type 0x%x"
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
+virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
+virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9f34d0e6619c..14091b191ec0 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -525,7 +525,7 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d60b1b2973af..602952a7041b 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1066,7 +1066,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 if (g->stats.max_inflight < g->inflight) {
 g->stats.max_inflight = g->inflight;
 }
-fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
+trace_virtio_gpu_inc_inflight_fences(g->inflight);
 }
 } else {
 g_free(cmd);
@@ -1086,7 +1086,7 @@ static void virtio_gpu_process_fenceq(VirtIOGPU *g)
 g_free(cmd);
 g->inflight--;
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
+trace_virtio_gpu_dec_inflight_fences(g->inflight);
 }
 }
 }
-- 
2.44.0




[PATCH v14 08/14] virtio-gpu: Don't require udmabuf when blobs and virgl are enabled

2024-06-15 Thread Dmitry Osipenko
The udmabuf usage is mandatory when virgl is disabled and blobs feature
enabled in the Qemu machine configuration. If virgl and blobs are enabled,
then udmabuf requirement is optional. Since udmabuf isn't widely supported
by a popular Linux distros today, let's relax the udmabuf requirement for
blobs=on,virgl=on. Now, a full-featured virtio-gpu acceleration is
available to Qemu users without a need to have udmabuf available in the
system.

Reviewed-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 602952a7041b..40a9d089710c 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1485,6 +1485,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 
 if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
 if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
+!virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
 !virtio_gpu_have_udmabuf()) {
 error_setg(errp, "need rutabaga or udmabuf for blob resources");
 return;
-- 
2.44.0




[PATCH v14 13/14] virtio-gpu: Register capsets dynamically

2024-06-15 Thread Dmitry Osipenko
From: Pierre-Eric Pelloux-Prayer 

virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
like Venus and DRM capsets. Register capsets dynamically to avoid that problem.

Reviewed-by: Manos Pitsidianakis 
Signed-off-by: Pierre-Eric Pelloux-Prayer 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  6 --
 hw/display/virtio-gpu-virgl.c  | 33 +
 include/hw/virtio/virtio-gpu.h |  4 +++-
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 5f27568d3ec8..20a7c316bb23 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -138,8 +138,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 }
 
 g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
-VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
-virtio_gpu_virgl_get_num_capsets(g);
+g->capset_ids = virtio_gpu_virgl_get_capsets(g);
+VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
 
 #if VIRGL_VERSION_MAJOR >= 1
 g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
@@ -171,6 +171,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 }
 
 gl->renderer_state = RS_START;
+
+g_array_unref(g->capset_ids);
 }
 
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index fed3e27b2fc9..8f3920800517 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -630,19 +630,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 VIRTIO_GPU_FILL_CMD(info);
 
 memset(&resp, 0, sizeof(resp));
-if (info.capset_index == 0) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
-virgl_renderer_get_cap_set(resp.capset_id,
-   &resp.capset_max_version,
-   &resp.capset_max_size);
-} else if (info.capset_index == 1) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+
+if (info.capset_index < g->capset_ids->len) {
+resp.capset_id = g_array_index(g->capset_ids, uint32_t,
+   info.capset_index);
 virgl_renderer_get_cap_set(resp.capset_id,
&resp.capset_max_version,
&resp.capset_max_size);
-} else {
-resp.capset_max_version = 0;
-resp.capset_max_size = 0;
 }
 resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
 virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
@@ -1164,12 +1158,27 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t capset_id)
+{
+g_array_append_val(capset_ids, capset_id);
+}
+
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
 uint32_t capset2_max_ver, capset2_max_size;
+GArray *capset_ids;
+
+capset_ids = g_array_new(false, false, sizeof(uint32_t));
+
+/* VIRGL is always supported. */
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
+
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
   &capset2_max_ver,
   &capset2_max_size);
+if (capset2_max_ver) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
+}
 
-return capset2_max_ver ? 2 : 1;
+return capset_ids;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 775005abb337..83232f4b4bfa 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -209,6 +209,8 @@ struct VirtIOGPU {
 QTAILQ_HEAD(, VGPUDMABuf) bufs;
 VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
 } dmabuf;
+
+GArray *capset_ids;
 };
 
 struct VirtIOGPUClass {
@@ -354,6 +356,6 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.44.0




[PATCH v14 07/14] virtio-gpu: Support context-init feature with virglrenderer

2024-06-15 Thread Dmitry Osipenko
From: Huang Rui 

Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
feature flags. Expose this feature and support creating virglrenderer
context with flags using context_id if libvirglrenderer is new enough.

Originally-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c|  4 
 hw/display/virtio-gpu-virgl.c | 20 ++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 0109244276fc..4fe9e6a0c21c 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -141,6 +141,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
*qdev, Error **errp)
 VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
 virtio_gpu_virgl_get_num_capsets(g);
 
+#if VIRGL_VERSION_MAJOR >= 1
+g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
+#endif
+
 virtio_gpu_device_realize(qdev, errp);
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index ca6f4d6cbb58..b3aa444bcfa5 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
 trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
 cc.debug_name);
 
-virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
-  cc.debug_name);
+if (cc.context_init) {
+if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+return;
+}
+
+#if VIRGL_VERSION_MAJOR >= 1
+virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
+ cc.context_init,
+ cc.nlen,
+ cc.debug_name);
+return;
+#endif
+}
+
+virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
 }
 
 static void virgl_cmd_context_destroy(VirtIOGPU *g,
-- 
2.44.0




[PATCH v14 04/14] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-15 Thread Dmitry Osipenko
virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
return code and don't execute virtio commands on error. Failed
virtio_gpu_virgl_init() will result in a timed out virtio commands
for a guest OS.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 30 ++
 include/hw/virtio/virtio-gpu.h | 11 +--
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index e06be60dfbfc..21a1e9a05c5d 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  struct virtio_gpu_scanout *s,
  uint32_t resource_id)
 {
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 uint32_t width, height;
 uint32_t pixels, *data;
 
+if (gl->renderer_state != RS_INITED) {
+return;
+}
+
 data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
 if (!data) {
 return;
@@ -65,13 +70,22 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, 
VirtQueue *vq)
 return;
 }
 
-if (!gl->renderer_inited) {
-virtio_gpu_virgl_init(g);
-gl->renderer_inited = true;
-}
-if (gl->renderer_reset) {
-gl->renderer_reset = false;
+switch (gl->renderer_state) {
+case RS_RESET:
 virtio_gpu_virgl_reset(g);
+/* fallthrough */
+case RS_START:
+if (virtio_gpu_virgl_init(g)) {
+gl->renderer_state = RS_INIT_FAILED;
+return;
+}
+
+gl->renderer_state = RS_INITED;
+break;
+case RS_INIT_FAILED:
+return;
+case RS_INITED:
+break;
 }
 
 cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
@@ -98,9 +112,9 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
  * GL functions must be called with the associated GL context in main
  * thread, and when the renderer is unblocked.
  */
-if (gl->renderer_inited && !gl->renderer_reset) {
+if (gl->renderer_state == RS_INITED) {
 virtio_gpu_virgl_reset_scanout(g);
-gl->renderer_reset = true;
+gl->renderer_state = RS_RESET;
 }
 }
 
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7ff989a45a5c..6e71d799e5da 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -224,11 +224,18 @@ struct VirtIOGPUClass {
  Error **errp);
 };
 
+/* VirtIOGPUGL renderer states */
+typedef enum {
+RS_START,   /* starting state */
+RS_INIT_FAILED, /* failed initialisation */
+RS_INITED,  /* initialised and working */
+RS_RESET,   /* inited and reset pending, moves to start after reset */
+} RenderState;
+
 struct VirtIOGPUGL {
 struct VirtIOGPU parent_obj;
 
-bool renderer_inited;
-bool renderer_reset;
+RenderState renderer_state;
 
 QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
-- 
2.44.0




[PATCH v14 00/14] Support blob memory and venus on qemu

2024-06-15 Thread Dmitry Osipenko
us"

Changes from V4 (virtio gpu V4) to V5

- Inverted patch 5 and 6 because we should configure
  HAVE_VIRGL_CONTEXT_INIT firstly.

- Validate owner of memory region to avoid slowing down DMA.

- Use memory_region_init_ram_ptr() instead of
  memory_region_init_ram_device_ptr().

- Adjust sequence to allocate gpu resource before virglrender resource
  creation

- Add virtio migration handling for uuid.

- Send kernel patch to define VIRTIO_GPU_CAPSET_VENUS.
  https://lore.kernel.org/lkml/20230915105918.3763061-1-ray.hu...@amd.com/

- Add meson check to make sure unstable APIs defined from 0.9.0.

Changes from V1 to V2 (virtio gpu V4)

- Remove unused #include "hw/virtio/virtio-iommu.h"

- Add a local function, called virgl_resource_destroy(), that is used
  to release a vgpu resource on error paths and in resource_unref.

- Remove virtio_gpu_virgl_resource_unmap from
  virtio_gpu_cleanup_mapping(),
  since this function won't be called on blob resources and also because
  blob resources are unmapped via virgl_cmd_resource_unmap_blob().

- In virgl_cmd_resource_create_blob(), do proper cleanup in error paths
  and move QTAILQ_INSERT_HEAD(&g->reslist, res, next) after the resource
  has been fully initialized.

- Memory region has a different life-cycle from virtio gpu resources
  i.e. cannot be released synchronously along with the vgpu resource.
  So, here the field "region" was changed to a pointer and is allocated
  dynamically when the blob is mapped.
  Also, since the pointer can be used to indicate whether the blob
  is mapped, the explicite field "mapped" was removed.

- In virgl_cmd_resource_map_blob(), add check on the value of
  res->region, to prevent beeing called twice on the same resource.

- Add a patch to enable automatic deallocation of memory regions to resolve
  use-after-free memory corruption with a reference.


Antonio Caggiano (2):
  virtio-gpu: Handle resource blob commands
  virtio-gpu: Support Venus context

Dmitry Osipenko (8):
  virtio-gpu: Use trace events for tracking number of in-flight fences
  virtio-gpu: Move fence_poll timer to VirtIOGPUGL
  virtio-gpu: Move print_stats timer to VirtIOGPUGL
  virtio-gpu: Handle virtio_gpu_virgl_init() failure
  virtio-gpu: Unrealize GL device
  virtio-gpu: Use pkgconfig version to decide which virgl features are
available
  virtio-gpu: Don't require udmabuf when blobs and virgl are enabled
  virtio-gpu: Support suspension of commands processing

Huang Rui (2):
  virtio-gpu: Support context-init feature with virglrenderer
  virtio-gpu: Add virgl resource management

Pierre-Eric Pelloux-Prayer (1):
  virtio-gpu: Register capsets dynamically

Robert Beckett (1):
  virtio-gpu: Support blob scanout using dmabuf fd

 hw/display/trace-events|   3 +
 hw/display/virtio-gpu-gl.c |  62 +++-
 hw/display/virtio-gpu-virgl.c  | 589 +++--
 hw/display/virtio-gpu.c|  44 ++-
 include/hw/virtio/virtio-gpu.h |  32 +-
 meson.build|   5 +-
 6 files changed, 678 insertions(+), 57 deletions(-)

-- 
2.44.0




[PATCH v14 06/14] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-06-15 Thread Dmitry Osipenko
New virglrerenderer features were stabilized with release of v1.0.0.
Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
with pre-release development versions of libvirglerender. Use virglrenderer
version to decide reliably which virgl features are available.

Reviewed-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 2 +-
 meson.build   | 5 +
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index a63d1f540f04..ca6f4d6cbb58 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -171,7 +171,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
 struct virgl_renderer_resource_info info;
 void *d3d_tex2d = NULL;
 
-#ifdef HAVE_VIRGL_D3D_INFO_EXT
+#if VIRGL_VERSION_MAJOR >= 1
 struct virgl_renderer_resource_info_ext ext;
 memset(&ext, 0, sizeof(ext));
 ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
diff --git a/meson.build b/meson.build
index 97e00d6f59b8..838d08ef0f9b 100644
--- a/meson.build
+++ b/meson.build
@@ -2329,10 +2329,7 @@ config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.found()
-  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
-   cc.has_member('struct 
virgl_renderer_resource_info_ext', 'd3d_tex2d',
- prefix: '#include ',
- dependencies: virgl))
+  config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.44.0




[PATCH v14 14/14] virtio-gpu: Support Venus context

2024-06-15 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 15 +++
 include/hw/virtio/virtio-gpu.h |  3 +++
 4 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 20a7c316bb23..9be452547322 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -151,6 +151,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 8f3920800517..ec923cf36ef7 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1132,6 +1132,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#if VIRGL_VERSION_MAJOR >= 1
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs);
 if (ret != 0) {
@@ -1165,7 +1170,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1174,11 +1179,20 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  &capset2_max_ver,
-  &capset2_max_size);
-if (capset2_max_ver) {
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index a5db2256a4bb..50b5634af13f 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1507,6 +1507,21 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef VIRGL_VERSION_MAJOR
+#if VIRGL_VERSION_MAJOR >= 1
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+#endif
+}
+
 if (!virtio_gpu_base_device_realize(qdev,
 virtio_gpu_handle_ctrl_cb,
 virtio_gpu_handle_cursor_cb,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 83232f4b4bfa..230fa0c4ee0a 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -99,6 +99,7 @@ enum virtio_gpu_base_conf_flags {
 VIRTIO_GPU_FLAG_BLOB_ENABLED,
 VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED,
 VIRTIO_GPU_FLAG_RUTABAGA_ENABLED,
+VIRTIO_GPU_FLAG_VENUS_ENABLED,
 };
 
 #define virtio_gpu_virgl_enabled(_cfg) \
@@ -117,6 +118,8 @@ enum virtio_gpu_base_conf_flags {
 (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED))
 #define virtio_gpu_hostmem_enabled(_cfg) \
 (_cfg.hostmem > 0)
+#define virtio_gpu_venus_enabled(_cfg) \
+(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VENUS_ENABLED))
 
 struct virtio_gpu_base_conf {
 uint32_t max_outputs;
-- 
2.44.0




[PATCH v14 02/14] virtio-gpu: Move fence_poll timer to VirtIOGPUGL

2024-06-15 Thread Dmitry Osipenko
Move fence_poll timer to VirtIOGPUGL for consistency with cmdq_resume_bh
that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 8 +---
 include/hw/virtio/virtio-gpu.h | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 14091b191ec0..91dce90f9176 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -594,11 +594,12 @@ static void virtio_gpu_print_stats(void *opaque)
 static void virtio_gpu_fence_poll(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 virgl_renderer_poll();
 virtio_gpu_process_cmdq(g);
 if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
-timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
+timer_mod(gl->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
 }
 }
 
@@ -626,6 +627,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 {
 int ret;
 uint32_t flags = 0;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 if (qemu_egl_display) {
@@ -645,8 +647,8 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return ret;
 }
 
-g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- virtio_gpu_fence_poll, g);
+gl->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+  virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a7a..bc69fd78a440 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
 
 uint32_t inflight;
@@ -231,6 +230,8 @@ struct VirtIOGPUGL {
 
 bool renderer_inited;
 bool renderer_reset;
+
+QEMUTimer *fence_poll;
 };
 
 struct VhostUserGPU {
-- 
2.44.0




[PATCH v14 05/14] virtio-gpu: Unrealize GL device

2024-06-15 Thread Dmitry Osipenko
Even though GL GPU doesn't support hotplugging today, free virgl
resources when GL device is unrealized. For consistency.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 21a1e9a05c5d..0109244276fc 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -150,6 +150,22 @@ static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
+{
+VirtIOGPU *g = VIRTIO_GPU(qdev);
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
+
+if (gl->renderer_state >= RS_INITED) {
+if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
+timer_free(gl->print_stats);
+}
+timer_free(gl->fence_poll);
+virgl_renderer_cleanup(NULL);
+}
+
+gl->renderer_state = RS_START;
+}
+
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -163,6 +179,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
void *data)
 vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
 
 vdc->realize = virtio_gpu_gl_device_realize;
+vdc->unrealize = virtio_gpu_gl_device_unrealize;
 vdc->reset = virtio_gpu_gl_reset;
 device_class_set_props(dc, virtio_gpu_gl_properties);
 }
-- 
2.44.0




[PATCH v14 03/14] virtio-gpu: Move print_stats timer to VirtIOGPUGL

2024-06-15 Thread Dmitry Osipenko
Move print_stats timer to VirtIOGPUGL for consistency with
cmdq_resume_bh and fence_poll that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 10 ++
 include/hw/virtio/virtio-gpu.h |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 91dce90f9176..a63d1f540f04 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -574,6 +574,7 @@ static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
 static void virtio_gpu_print_stats(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 if (g->stats.requests) {
 fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
@@ -588,7 +589,7 @@ static void virtio_gpu_print_stats(void *opaque)
 } else {
 fprintf(stderr, "stats: idle\r");
 }
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+timer_mod(gl->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 static void virtio_gpu_fence_poll(void *opaque)
@@ -651,9 +652,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
   virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
-  virtio_gpu_print_stats, g);
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 
1000);
+gl->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+   virtio_gpu_print_stats, g);
+timer_mod(gl->print_stats,
+  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 return 0;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index bc69fd78a440..7ff989a45a5c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *print_stats;
 
 uint32_t inflight;
 struct {
@@ -232,6 +231,7 @@ struct VirtIOGPUGL {
 bool renderer_reset;
 
 QEMUTimer *fence_poll;
+QEMUTimer *print_stats;
 };
 
 struct VhostUserGPU {
-- 
2.44.0




[PATCH v14 09/14] virtio-gpu: Add virgl resource management

2024-06-15 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b3aa444bcfa5..3ffea478e723 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
&res_iovs,
&num_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs);
 }
 virgl_renderer_resource_unref(unref.resource_id);
+
+QTAILQ_REMOVE(&g->reslist, &res->base, next);
+
+g_free(res);
 }
 
 static void virgl_cmd_context_create(VirtIOGPU *g,
-- 
2.44.0




[PATCH v14 12/14] virtio-gpu: Handle resource blob commands

2024-06-15 Thread Dmitry Osipenko
From: Antonio Caggiano 

Support BLOB resources creation, mapping and unmapping by calling the
new stable virglrenderer 0.10 interface. Only enabled when available and
via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |   3 +
 hw/display/virtio-gpu-virgl.c  | 309 -
 hw/display/virtio-gpu.c|   6 +-
 include/hw/virtio/virtio-gpu.h |   2 +
 4 files changed, 316 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 4fe9e6a0c21c..5f27568d3ec8 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -160,6 +160,9 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
 
 if (gl->renderer_state >= RS_INITED) {
+#if VIRGL_VERSION_MAJOR >= 1
+qemu_bh_delete(gl->cmdq_resume_bh);
+#endif
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 timer_free(gl->print_stats);
 }
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 60befab7efc2..fed3e27b2fc9 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -26,6 +26,7 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -49,6 +50,153 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#if VIRGL_VERSION_MAJOR >= 1
+typedef enum {
+HOSTMEM_MR_MAPPED,
+HOSTMEM_MR_UNMAPPING,
+HOSTMEM_MR_FINISH_UNMAPPING,
+} HostmemMRState;
+
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+HostmemMRState state;
+};
+
+static struct virtio_gpu_virgl_hostmem_region *
+to_hostmem_region(MemoryRegion *mr)
+{
+return container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+}
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+VirtIOGPUGL *gl;
+
+vmr = to_hostmem_region(mr);
+vmr->state = HOSTMEM_MR_FINISH_UNMAPPING;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+gl = VIRTIO_GPU_GL(vmr->g);
+qemu_bh_schedule(gl->cmdq_resume_bh);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->g = g;
+
+mr = &vmr->mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(&b->hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
+ struct virtio_gpu_virgl_resource *res,
+ bool *cmd_suspended)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+int ret;
+
+if (!mr) {
+return 0;
+}
+
+vmr = to_hostmem_region(res->mr);
+
+/*
+ * Perform async unmapping in 3 steps:
+ *
+ * 1. Begin async unmapping with memory_region_del_subregion()
+ *and suspend/block cmd processing.
+ * 2. Wa

[PATCH v14 10/14] virtio-gpu: Support blob scanout using dmabuf fd

2024-06-15 Thread Dmitry Osipenko
From: Robert Beckett 

Support displaying blob resources by handling SET_SCANOUT_BLOB
command.

Signed-by: Antonio Caggiano 
Signed-off-by: Robert Beckett 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 109 +
 hw/display/virtio-gpu.c|  12 ++--
 include/hw/virtio/virtio-gpu.h |   7 +++
 3 files changed, 122 insertions(+), 6 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 3ffea478e723..60befab7efc2 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 res->base.height = c2d.height;
 res->base.format = c2d.format;
 res->base.resource_id = c2d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c2d.resource_id;
@@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 res->base.height = c3d.height;
 res->base.format = c3d.format;
 res->base.resource_id = c3d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c3d.resource_id;
@@ -509,6 +513,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
 g_free(resp);
 }
 
+#if VIRGL_VERSION_MAJOR >= 1
+static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
+   struct virtio_gpu_ctrl_command *cmd)
+{
+struct virtio_gpu_framebuffer fb = { 0 };
+struct virgl_renderer_resource_info info;
+struct virtio_gpu_virgl_resource *res;
+struct virtio_gpu_set_scanout_blob ss;
+uint64_t fbend;
+
+VIRTIO_GPU_FILL_CMD(ss);
+virtio_gpu_scanout_blob_bswap(&ss);
+trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
+  ss.r.width, ss.r.height, ss.r.x,
+  ss.r.y);
+
+if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+  __func__, ss.scanout_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+return;
+}
+
+if (ss.resource_id == 0) {
+virtio_gpu_disable_scanout(g, ss.scanout_id);
+return;
+}
+
+if (ss.width < 16 ||
+ss.height < 16 ||
+ss.r.x + ss.r.width > ss.width ||
+ss.r.y + ss.r.height > ss.height) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
+  __func__, ss.scanout_id, ss.resource_id,
+  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
+  ss.width, ss.height);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (virgl_renderer_resource_get_info(ss.resource_id, &info)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have info %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (res->base.dmabuf_fd < 0) {
+res->base.dmabuf_fd = info.fd;
+}
+if (res->base.dmabuf_fd < 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource not backed by dmabuf 
%d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+fb.format = virtio_gpu_get_pixman_format(ss.format);
+if (!fb.format) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: pixel format not supported %d\n",
+  __func__, ss.format);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+fb.width = ss.width;
+fb.height = ss.height;
+fb.stride = ss.strides[0];
+fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
+
+fbend = fb.offset;
+fbend += fb.stride * (ss.r.height - 1);
+fbend += fb.bytes_pp * ss.r.width;
+if (fbend > res-

[PATCH v14 11/14] virtio-gpu: Support suspension of commands processing

2024-06-15 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/trace-events | 1 +
 hw/display/virtio-gpu.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/hw/display/trace-events b/hw/display/trace-events
index e212710284ae..d26d663f9638 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -55,6 +55,7 @@ virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 
0x%" PRIx64 ", type
 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
 virtio_gpu_inc_inflight_fences(uint32_t inflight) "in-flight+ %u"
 virtio_gpu_dec_inflight_fences(uint32_t inflight) "in-flight- %u"
+virtio_gpu_cmd_suspended(uint32_t cmd) "cmd 0x%x"
 
 # qxl.c
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t 
val) "%d %s addr=%u val=%u"
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 95091c4b7924..1c6e97fb6931 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1054,6 +1054,12 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+trace_virtio_gpu_cmd_suspended(cmd->cmd_hdr.type);
+break;
+}
+
 QTAILQ_REMOVE(&g->cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.44.0




Re: [PATCH v13 03/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-15 Thread Dmitry Osipenko
On 6/10/24 06:38, Akihiko Odaki wrote:
> On 2024/06/10 4:02, Dmitry Osipenko wrote:
>> On 6/3/24 08:44, Akihiko Odaki wrote:
>>> On 2024/06/03 14:26, Dmitry Osipenko wrote:
>>>> On 6/2/24 08:34, Akihiko Odaki wrote:
>>>>>> +typedef enum {
>>>>>> +    RS_START,   /* starting state */
>>>>>> +    RS_INIT_FAILED, /* failed initialisation */
>>>>>
>>>>> Is the distinction between RS_START and RS_INIT_FAILED really
>>>>> necessary?
>>>>
>>>> The state stays in RS_INIT_FAILED once was failed until virtio-gpu is
>>>> reset, re-initializing virglrenderer isn't allowed in this state.
>>>
>>> Can you elaborate more? Why isn't re-initializing allowed?
>>
>> In practice, if virglrenderer initialization failed once, it will fail
>> second time. Otherwise we will be retrying to init endlessly because
>> guest won't stop sending virgl commands even if they all are timing out.
>> Each initialization failure produces a error msg.
>>
> I see.
> 
> A better solution is to add a new function to GraphicHwOps to call back
> after initializating the displays and before starting the guest. You can
> do virgl initialization in such a function, and exit(1) if the
> initialization fails because the guest has not started yet, saving this
> enum. I don't require you to make such a change however; this is not a
> regression of your patches so you have no obligation to fix it.

I'll keep this idea for a follow up patch, thanks! It will take me some
extra time to look through the display code, making sure that callback
is added properly and nothing is missed.

-- 
Best regards,
Dmitry




Re: [PATCH v13 03/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-09 Thread Dmitry Osipenko
On 6/4/24 17:21, Marc-André Lureau wrote:
>> @@ -65,13 +70,21 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice
>> *vdev, VirtQueue *vq)
>>  return;
>>  }
>>
>> -if (!gl->renderer_inited) {
>> -virtio_gpu_virgl_init(g);
>> -gl->renderer_inited = true;
>> -}
>> -if (gl->renderer_reset) {
>> -gl->renderer_reset = false;
>> +switch (gl->renderer_state) {
>> +case RS_RESET:
>>  virtio_gpu_virgl_reset(g);
>> +/* fallthrough */
>> +case RS_START:
>> +if (virtio_gpu_virgl_init(g)) {
>> +gl->renderer_state = RS_INIT_FAILED;
>> +} else {
>> +gl->renderer_state = RS_INITED;
>> +}
>> +break;
>> +case RS_INIT_FAILED:
>> +return;
>> +case RS_INITED:
>> +break;
>>  }
>>
>>
> This still lets it go through the cmd processing after setting
> gl->renderer_state = RS_INIT_FAILED, the first time.

Good catch, thanks!

-- 
Best regards,
Dmitry




Re: [PATCH v13 03/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-09 Thread Dmitry Osipenko
On 6/3/24 08:44, Akihiko Odaki wrote:
> On 2024/06/03 14:26, Dmitry Osipenko wrote:
>> On 6/2/24 08:34, Akihiko Odaki wrote:
>>>> +typedef enum {
>>>> +    RS_START,   /* starting state */
>>>> +    RS_INIT_FAILED, /* failed initialisation */
>>>
>>> Is the distinction between RS_START and RS_INIT_FAILED really necessary?
>>
>> The state stays in RS_INIT_FAILED once was failed until virtio-gpu is
>> reset, re-initializing virglrenderer isn't allowed in this state.
> 
> Can you elaborate more? Why isn't re-initializing allowed?

In practice, if virglrenderer initialization failed once, it will fail
second time. Otherwise we will be retrying to init endlessly because
guest won't stop sending virgl commands even if they all are timing out.
Each initialization failure produces a error msg.

-- 
Best regards,
Dmitry




Re: [PATCH v12 00/13] Support blob memory and venus on qemu

2024-06-05 Thread Dmitry Osipenko
On 6/5/24 17:47, Alex Bennée wrote:

> I'm guessing some sort of resource leak, if I run vkcube-wayland in the
> guest it complains about being stuck on a fence with the iterator going
> up. However on the host I see:
> 
>   virtio_gpu_fence_ctrl fence 0x13f1, type 0x207
>   virtio_gpu_fence_ctrl fence 0x13f2, type 0x207
>   virtio_gpu_fence_resp fence 0x13f1
>   virtio_gpu_fence_resp fence 0x13f2
>   virtio_gpu_fence_ctrl fence 0x13f3, type 0x207
>   virtio_gpu_fence_ctrl fence 0x13f4, type 0x207
>   virtio_gpu_fence_resp fence 0x13f3
>   virtio_gpu_fence_resp fence 0x13f4
>   virtio_gpu_fence_ctrl fence 0x13f5, type 0x207
>   virtio_gpu_fence_ctrl fence 0x13f6, type 0x207
>   virtio_gpu_fence_resp fence 0x13f5
>   virtio_gpu_fence_resp fence 0x13f6
>   virtio_gpu_fence_ctrl fence 0x13f7, type 0x207
>   virtio_gpu_fence_ctrl fence 0x13f8, type 0x207
>   virtio_gpu_fence_resp fence 0x13f7
>   virtio_gpu_fence_resp fence 0x13f8
>   virtio_gpu_fence_ctrl fence 0x13f9, type 0x204
>   virtio_gpu_fence_resp fence 0x13f9
> 
> which looks like its going ok. However when I git Ctrl-C in the guest it
> kills QEMU:
> 
>   virtio_gpu_fence_ctrl fence 0x13fc, type 0x207
>   virtio_gpu_fence_ctrl fence 0x13fd, type 0x207
>   virtio_gpu_fence_ctrl fence 0x13fe, type 0x204
>   virtio_gpu_fence_ctrl fence 0x13ff, type 0x207
>   virtio_gpu_fence_ctrl fence 0x1400, type 0x207
>   virtio_gpu_fence_resp fence 0x13fc
>   virtio_gpu_fence_resp fence 0x13fd
>   virtio_gpu_fence_resp fence 0x13fe
>   virtio_gpu_fence_resp fence 0x13ff
>   virtio_gpu_fence_resp fence 0x1400
>   qemu-system-aarch64: 
> ../../subprojects/virglrenderer/src/virglrenderer.c:1282: 
> virgl_renderer_resource_unmap: Assertion `!ret' failed.
>   fish: Job 1, './qemu-system-aarch64 \' terminated by signal -machine 
> type=virt,virtuali… (-cpu neoverse-n1 \)
>   fish: Job -smp 4 \, '-accel tcg \' terminated by signal -device 
> virtio-net-pci,netd… (-device virtio-scsi-pci \)
>   fish: Job -device scsi-hd,drive=hd \, '-netdev 
> user,id=unet,hostfw…' terminated by signal -blockdev driver=raw,node-n… ( 
>-serial mon:stdio \)
>   fish: Job -blockdev node-name=rom,dri…, '-blockdev 
> node-name=efivars…' terminated by signal -m 8192 \ (-object 
> memory-backend-memf…)
>   fish: Job -device virtio-gpu-gl-pci,h…, '-display 
> sdl,gl=on,show-cur…' terminated by signal -device qemu-xhci -device u… (  
>   -kernel /home/alex/lsrc/lin…)
>   fish: Job -d guest_errors,unimp,trace…, 'SIGABRT' terminated by signal 
> Abort ()
> 
> The backtrace (and the 18G size of the core file!) indicates a leak:

The unmap debug-assert tells that BO wasn't mapped because mapping
failed, likely due to OOM. You won't hit this abort with a release build
of libvirglrenderer. The leak likely happens due to unsignalled fence.

Please try to run vkcube with disabled fence-feedback feature:

 # VN_PERF_NO_FENCE_FEEDBACK=1 vkcube-wayland

It fixes hang for me. We had problems with combination of this Venus
optimization feature + Intel ANV driver for a long time and hoped that
it's fixed by now, apparently the issue was only masked.

-- 
Best regards,
Dmitry




Re: [PATCH v13 11/13] virtio-gpu: Handle resource blob commands

2024-06-02 Thread Dmitry Osipenko
On 6/2/24 08:45, Akihiko Odaki wrote:
...
>> +    case HOSTMEM_MR_FINISH_UNMAPPING:
>> +    ret = virgl_renderer_resource_unmap(res->base.resource_id);
>> +    if (ret) {
>> +    qemu_log_mask(LOG_GUEST_ERROR,
>> +  "%s: failed to unmap virgl resource: %s\n",
>> +  __func__, strerror(-ret));
>> +    return ret;
>> +    }
>> +    res->mr = NULL;
>> +    g_free(vmr);
>> +    break;
>> +    case HOSTMEM_MR_UNMAPPING:
>> +    *cmd_suspended = true;
> 
> This code path should be unreachable since the command processing is
> blocked while unmapping.

Will change to abort()

>> +    if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_HOST3D) {
>> +    ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries,
>> sizeof(cblob),
>> +    cmd, &res->base.addrs,
>> +    &res->base.iov,
>> &res->base.iov_cnt);
>> +    if (!ret) {
>> +    g_free(res);
> 
> As noted for an earlier version:
>> Use g_autofree instead of writing duplicate g_free() calls. See
>> docs/devel/style.rst for details.

The g_autofree isn't appropriate for this code. It's intended to be used
if you allocate a tmp variable that should be freed in all code paths.
This is not the case here, the res variable isn't temporal and shall not
be freed on success.

-- 
Best regards,
Dmitry




Re: [PATCH v13 03/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-02 Thread Dmitry Osipenko
On 6/2/24 08:34, Akihiko Odaki wrote:
>> +typedef enum {
>> +    RS_START,   /* starting state */
>> +    RS_INIT_FAILED, /* failed initialisation */
> 
> Is the distinction between RS_START and RS_INIT_FAILED really necessary?

The state stays in RS_INIT_FAILED once was failed until virtio-gpu is
reset, re-initializing virglrenderer isn't allowed in this state.

The RS_START state allows to initialize virglrenderer and moves to
either RS_INITED or RS_INIT_FAILED state after initialization.

The distinction is necessary

-- 
Best regards,
Dmitry




[PATCH v13 11/13] virtio-gpu: Handle resource blob commands

2024-05-26 Thread Dmitry Osipenko
From: Antonio Caggiano 

Support BLOB resources creation, mapping and unmapping by calling the
new stable virglrenderer 0.10 interface. Only enabled when available and
via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 320 -
 hw/display/virtio-gpu.c|   4 +-
 include/hw/virtio/virtio-gpu.h |   2 +
 3 files changed, 322 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 7f45b4fa5fd7..0c73d9ba65f9 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -26,6 +26,7 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -49,6 +50,159 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#ifdef HAVE_VIRGL_RESOURCE_BLOB
+typedef enum {
+HOSTMEM_MR_MAPPED,
+HOSTMEM_MR_UNMAPPING,
+HOSTMEM_MR_FINISH_UNMAPPING,
+} HostmemMRState;
+
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+HostmemMRState state;
+};
+
+static struct virtio_gpu_virgl_hostmem_region *
+to_hostmem_region(MemoryRegion *mr)
+{
+return container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+}
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+VirtIOGPUGL *gl;
+
+vmr = to_hostmem_region(mr);
+vmr->state = HOSTMEM_MR_FINISH_UNMAPPING;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+gl = VIRTIO_GPU_GL(vmr->g);
+qemu_bh_schedule(gl->cmdq_resume_bh);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->g = g;
+
+mr = &vmr->mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(&b->hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
+ struct virtio_gpu_virgl_resource *res,
+ bool *cmd_suspended)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+int ret;
+
+if (!mr) {
+return 0;
+}
+
+vmr = to_hostmem_region(res->mr);
+
+/*
+ * Perform async unmapping in 3 steps:
+ *
+ * 1. Begin async unmapping with memory_region_del_subregion()
+ *and suspend/block cmd processing.
+ * 2. Wait for res->mr to be freed and cmd processing resumed
+ *asynchronously by virtio_gpu_virgl_hostmem_region_free().
+ * 3. Finish the unmapping with final virgl_renderer_resource_unmap().
+ */
+
+switch (vmr->state) {
+case HOSTMEM_MR_MAPPED:
+vmr->state = HOSTMEM_MR_UNMAPPING;
+
+*cmd_suspended = true;
+
+/* render will be unblocked once MR is freed */
+b->renderer_blocked++;
+
+/* memory region owns self res->mr object and frees it by itself */
+memory_region_set_enabled(mr, false);
+memory_region_del_subreg

[PATCH v13 02/13] virtio-gpu: Move print_stats timer to VirtIOGPUGL

2024-05-26 Thread Dmitry Osipenko
Move print_stats timer to VirtIOGPUGL for consistency with
cmdq_resume_bh and fence_poll that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 10 ++
 include/hw/virtio/virtio-gpu.h |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 7239a9f8e066..fa0da8f5c7f1 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -574,6 +574,7 @@ static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
 static void virtio_gpu_print_stats(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 if (g->stats.requests) {
 fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
@@ -588,7 +589,7 @@ static void virtio_gpu_print_stats(void *opaque)
 } else {
 fprintf(stderr, "stats: idle\r");
 }
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+timer_mod(gl->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 static void virtio_gpu_fence_poll(void *opaque)
@@ -651,9 +652,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
   virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
-  virtio_gpu_print_stats, g);
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 
1000);
+gl->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+   virtio_gpu_print_stats, g);
+timer_mod(gl->print_stats,
+  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 return 0;
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index bc69fd78a440..7ff989a45a5c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *print_stats;
 
 uint32_t inflight;
 struct {
@@ -232,6 +231,7 @@ struct VirtIOGPUGL {
 bool renderer_reset;
 
 QEMUTimer *fence_poll;
+QEMUTimer *print_stats;
 };
 
 struct VhostUserGPU {
-- 
2.44.0




[PATCH v13 07/13] virtio-gpu: Don't require udmabuf when blobs and virgl are enabled

2024-05-26 Thread Dmitry Osipenko
The udmabuf usage is mandatory when virgl is disabled and blobs feature
enabled in the Qemu machine configuration. If virgl and blobs are enabled,
then udmabuf requirement is optional. Since udmabuf isn't widely supported
by a popular Linux distros today, let's relax the udmabuf requirement for
blobs=on,virgl=on. Now, a full-featured virtio-gpu acceleration is
available to Qemu users without a need to have udmabuf available in the
system.

Reviewed-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d60b1b2973af..672279e57f3f 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1485,6 +1485,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 
 if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
 if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
+!virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
 !virtio_gpu_have_udmabuf()) {
 error_setg(errp, "need rutabaga or udmabuf for blob resources");
 return;
-- 
2.44.0




[PATCH v13 12/13] virtio-gpu: Register capsets dynamically

2024-05-26 Thread Dmitry Osipenko
From: Pierre-Eric Pelloux-Prayer 

virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
like Venus and DRM capsets. Register capsets dynamically to avoid that problem.

Reviewed-by: Manos Pitsidianakis 
Signed-off-by: Pierre-Eric Pelloux-Prayer 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  6 --
 hw/display/virtio-gpu-virgl.c  | 33 +
 include/hw/virtio/virtio-gpu.h |  4 +++-
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 9822d79c5e81..34a2bd2fa426 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -137,8 +137,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 }
 
 g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
-VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
-virtio_gpu_virgl_get_num_capsets(g);
+g->capset_ids = virtio_gpu_virgl_get_capsets(g);
+VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
 
 #ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
 g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
@@ -163,6 +163,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 }
 
 gl->renderer_state = RS_START;
+
+g_array_unref(g->capset_ids);
 }
 
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 0c73d9ba65f9..d3ae3e3d4e24 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -636,19 +636,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 VIRTIO_GPU_FILL_CMD(info);
 
 memset(&resp, 0, sizeof(resp));
-if (info.capset_index == 0) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
-virgl_renderer_get_cap_set(resp.capset_id,
-   &resp.capset_max_version,
-   &resp.capset_max_size);
-} else if (info.capset_index == 1) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+
+if (info.capset_index < g->capset_ids->len) {
+resp.capset_id = g_array_index(g->capset_ids, uint32_t,
+   info.capset_index);
 virgl_renderer_get_cap_set(resp.capset_id,
&resp.capset_max_version,
&resp.capset_max_size);
-} else {
-resp.capset_max_version = 0;
-resp.capset_max_size = 0;
 }
 resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
 virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
@@ -1171,14 +1165,29 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t capset_id)
+{
+g_array_append_val(capset_ids, capset_id);
+}
+
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
 uint32_t capset2_max_ver, capset2_max_size;
+GArray *capset_ids;
+
+capset_ids = g_array_new(false, false, sizeof(uint32_t));
+
+/* VIRGL is always supported. */
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
+
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
   &capset2_max_ver,
   &capset2_max_size);
+if (capset2_max_ver) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
+}
 
-return capset2_max_ver ? 2 : 1;
+return capset_ids;
 }
 
 void virtio_gpu_virgl_deinit(VirtIOGPU *g)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 368f96a813c9..b9de761fd673 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -209,6 +209,8 @@ struct VirtIOGPU {
 QTAILQ_HEAD(, VGPUDMABuf) bufs;
 VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
 } dmabuf;
+
+GArray *capset_ids;
 };
 
 struct VirtIOGPUClass {
@@ -355,6 +357,6 @@ void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
 void virtio_gpu_virgl_deinit(VirtIOGPU *g);
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.44.0




[PATCH v13 13/13] virtio-gpu: Support Venus context

2024-05-26 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 13 +
 include/hw/virtio/virtio-gpu.h |  3 +++
 meson.build|  1 +
 5 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 34a2bd2fa426..50292826e7cf 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -150,6 +150,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index d3ae3e3d4e24..c9d20a8a60d0 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1139,6 +1139,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#ifdef VIRGL_RENDERER_VENUS
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs);
 if (ret != 0) {
@@ -1172,7 +1177,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1181,12 +1186,21 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  &capset2_max_ver,
-  &capset2_max_size);
-if (capset2_max_ver) {
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
 
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d423bc9a7bf5..0618801715a6 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1504,6 +1504,19 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef HAVE_VIRGL_VENUS
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+}
+
 if (!virtio_gpu_base_device_realize(qdev,
 virtio_gpu_handle_ctrl_cb,
 virtio_gpu_handle_cursor_cb,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index b9de761fd673..910c5c3bcd45 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -99,6 +99,7 @@ enum virtio_gpu_base_conf_flags {
 VIRTIO_GPU_FLAG_BLOB_ENABLED,
 VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED,
 VIRTIO_GPU_FLAG_RUTABAGA_ENABLED,
+VIRTIO_GPU_FLAG_VENUS_ENABLED,
 };
 
 #define virtio_gpu_virgl_enabled(_cfg) \
@@ -117,6 +118,8 @@ enum virtio_gpu_base_conf_flags {
 (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED))
 #define virtio_gpu_hostmem_enabled(_cfg) \
 (_cfg.hostmem > 0)
+#define virtio_gpu_venus_enabled(_cfg) \
+(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VENUS_ENABLED))
 
 struct virtio_gpu_base_conf {
 uint32_t max_outputs;
diff --git a/meson.build b/meson.build
index e753da4c76c3..1d7346b70311 100644
--- a/meson.build
+++ b/meson.build
@@ -2312,6 +2312,7 @@ if virgl.version().version_compare('>=1.0.0')
   config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT&#

[PATCH v13 10/13] virtio-gpu: Support suspension of commands processing

2024-05-26 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index f3d2def9a49f..8e05a2d0c7c5 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1054,6 +1054,11 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+break;
+}
+
 QTAILQ_REMOVE(&g->cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.44.0




[PATCH v13 06/13] virtio-gpu: Support context-init feature with virglrenderer

2024-05-26 Thread Dmitry Osipenko
From: Huang Rui 

Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
feature flags. Expose this feature and support creating virglrenderer
context with flags using context_id if libvirglrenderer is new enough.

Originally-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c|  4 
 hw/display/virtio-gpu-virgl.c | 20 ++--
 meson.build   |  1 +
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 7978b2985e17..9822d79c5e81 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -140,6 +140,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
*qdev, Error **errp)
 VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
 virtio_gpu_virgl_get_num_capsets(g);
 
+#ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
+g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
+#endif
+
 virtio_gpu_device_realize(qdev, errp);
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 66c4aab9b283..4b2d4a643e30 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
 trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
 cc.debug_name);
 
-virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
-  cc.debug_name);
+if (cc.context_init) {
+if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+return;
+}
+
+#ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
+virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
+ cc.context_init,
+ cc.nlen,
+ cc.debug_name);
+return;
+#endif
+}
+
+virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
 }
 
 static void virgl_cmd_context_destroy(VirtIOGPU *g,
diff --git a/meson.build b/meson.build
index de97d2426bde..65fddfbbc3a7 100644
--- a/meson.build
+++ b/meson.build
@@ -2310,6 +2310,7 @@ config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.version().version_compare('>=1.0.0')
   config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
+  config_host_data.set('HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS', 1)
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.44.0




[PATCH v13 03/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-05-26 Thread Dmitry Osipenko
virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
return code and don't execute virtio commands on error. Failed
virtio_gpu_virgl_init() will result in a timed out virtio commands
for a guest OS.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 29 +
 include/hw/virtio/virtio-gpu.h | 11 +--
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index e06be60dfbfc..38a2b1bd3916 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  struct virtio_gpu_scanout *s,
  uint32_t resource_id)
 {
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 uint32_t width, height;
 uint32_t pixels, *data;
 
+if (gl->renderer_state != RS_INITED) {
+return;
+}
+
 data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
 if (!data) {
 return;
@@ -65,13 +70,21 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, 
VirtQueue *vq)
 return;
 }
 
-if (!gl->renderer_inited) {
-virtio_gpu_virgl_init(g);
-gl->renderer_inited = true;
-}
-if (gl->renderer_reset) {
-gl->renderer_reset = false;
+switch (gl->renderer_state) {
+case RS_RESET:
 virtio_gpu_virgl_reset(g);
+/* fallthrough */
+case RS_START:
+if (virtio_gpu_virgl_init(g)) {
+gl->renderer_state = RS_INIT_FAILED;
+} else {
+gl->renderer_state = RS_INITED;
+}
+break;
+case RS_INIT_FAILED:
+return;
+case RS_INITED:
+break;
 }
 
 cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
@@ -98,9 +111,9 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
  * GL functions must be called with the associated GL context in main
  * thread, and when the renderer is unblocked.
  */
-if (gl->renderer_inited && !gl->renderer_reset) {
+if (gl->renderer_state == RS_INITED) {
 virtio_gpu_virgl_reset_scanout(g);
-gl->renderer_reset = true;
+gl->renderer_state = RS_RESET;
 }
 }
 
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7ff989a45a5c..6e71d799e5da 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -224,11 +224,18 @@ struct VirtIOGPUClass {
  Error **errp);
 };
 
+/* VirtIOGPUGL renderer states */
+typedef enum {
+RS_START,   /* starting state */
+RS_INIT_FAILED, /* failed initialisation */
+RS_INITED,  /* initialised and working */
+RS_RESET,   /* inited and reset pending, moves to start after reset */
+} RenderState;
+
 struct VirtIOGPUGL {
 struct VirtIOGPU parent_obj;
 
-bool renderer_inited;
-bool renderer_reset;
+RenderState renderer_state;
 
 QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
-- 
2.44.0




[PATCH v13 09/13] virtio-gpu: Support blob scanout using dmabuf fd

2024-05-26 Thread Dmitry Osipenko
From: Robert Beckett 

Support displaying blob resources by handling SET_SCANOUT_BLOB
command.

Signed-by: Antonio Caggiano 
Signed-off-by: Robert Beckett 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 109 +
 hw/display/virtio-gpu.c|  12 ++--
 include/hw/virtio/virtio-gpu.h |   7 +++
 meson.build|   1 +
 4 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 8392d0fde984..7f45b4fa5fd7 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 res->base.height = c2d.height;
 res->base.format = c2d.format;
 res->base.resource_id = c2d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c2d.resource_id;
@@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 res->base.height = c3d.height;
 res->base.format = c3d.format;
 res->base.resource_id = c3d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c3d.resource_id;
@@ -509,6 +513,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
 g_free(resp);
 }
 
+#ifdef HAVE_VIRGL_RESOURCE_BLOB
+static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
+   struct virtio_gpu_ctrl_command *cmd)
+{
+struct virtio_gpu_framebuffer fb = { 0 };
+struct virgl_renderer_resource_info info;
+struct virtio_gpu_virgl_resource *res;
+struct virtio_gpu_set_scanout_blob ss;
+uint64_t fbend;
+
+VIRTIO_GPU_FILL_CMD(ss);
+virtio_gpu_scanout_blob_bswap(&ss);
+trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
+  ss.r.width, ss.r.height, ss.r.x,
+  ss.r.y);
+
+if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+  __func__, ss.scanout_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+return;
+}
+
+if (ss.resource_id == 0) {
+virtio_gpu_disable_scanout(g, ss.scanout_id);
+return;
+}
+
+if (ss.width < 16 ||
+ss.height < 16 ||
+ss.r.x + ss.r.width > ss.width ||
+ss.r.y + ss.r.height > ss.height) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
+  __func__, ss.scanout_id, ss.resource_id,
+  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
+  ss.width, ss.height);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (virgl_renderer_resource_get_info(ss.resource_id, &info)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have info %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (res->base.dmabuf_fd < 0) {
+res->base.dmabuf_fd = info.fd;
+}
+if (res->base.dmabuf_fd < 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource not backed by dmabuf 
%d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+fb.format = virtio_gpu_get_pixman_format(ss.format);
+if (!fb.format) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: pixel format not supported %d\n",
+  __func__, ss.format);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+fb.width = ss.width;
+fb.height = ss.height;
+fb.stride = ss.strides[0];
+fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
+
+fbend = fb.offset;
+fbend += fb.stride * (ss.r.height - 1);
+fbend += fb.b

[PATCH v13 00/13] Support blob memory and venus on qemu

2024-05-26 Thread Dmitry Osipenko
o_gpu_virgl_resource_unmap from
  virtio_gpu_cleanup_mapping(),
  since this function won't be called on blob resources and also because
  blob resources are unmapped via virgl_cmd_resource_unmap_blob().

- In virgl_cmd_resource_create_blob(), do proper cleanup in error paths
  and move QTAILQ_INSERT_HEAD(&g->reslist, res, next) after the resource
  has been fully initialized.

- Memory region has a different life-cycle from virtio gpu resources
  i.e. cannot be released synchronously along with the vgpu resource.
  So, here the field "region" was changed to a pointer and is allocated
  dynamically when the blob is mapped.
  Also, since the pointer can be used to indicate whether the blob
  is mapped, the explicite field "mapped" was removed.

- In virgl_cmd_resource_map_blob(), add check on the value of
  res->region, to prevent beeing called twice on the same resource.

- Add a patch to enable automatic deallocation of memory regions to resolve
  use-after-free memory corruption with a reference.


Antonio Caggiano (2):
  virtio-gpu: Handle resource blob commands
  virtio-gpu: Support Venus context

Dmitry Osipenko (7):
  virtio-gpu: Move fence_poll timer to VirtIOGPUGL
  virtio-gpu: Move print_stats timer to VirtIOGPUGL
  virtio-gpu: Handle virtio_gpu_virgl_init() failure
  virtio-gpu: Unrealize GL device
  virtio-gpu: Use pkgconfig version to decide which virgl features are
available
  virtio-gpu: Don't require udmabuf when blobs and virgl are enabled
  virtio-gpu: Support suspension of commands processing

Huang Rui (2):
  virtio-gpu: Support context-init feature with virglrenderer
  virtio-gpu: Add virgl resource management

Pierre-Eric Pelloux-Prayer (1):
  virtio-gpu: Register capsets dynamically

Robert Beckett (1):
  virtio-gpu: Support blob scanout using dmabuf fd

 hw/display/virtio-gpu-gl.c |  54 ++-
 hw/display/virtio-gpu-virgl.c  | 607 +++--
 hw/display/virtio-gpu.c|  35 +-
 include/hw/virtio/virtio-gpu.h |  33 +-
 meson.build|  10 +-
 5 files changed, 685 insertions(+), 54 deletions(-)

-- 
2.44.0




[PATCH v13 05/13] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-05-26 Thread Dmitry Osipenko
New virglrerenderer features were stabilized with release of v1.0.0.
Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
with pre-release development versions of libvirglerender. Use virglrenderer
version to decide reliably which virgl features are available.

Reviewed-by: Alex Bennée 
Signed-off-by: Dmitry Osipenko 
---
 meson.build | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/meson.build b/meson.build
index 638660714455..de97d2426bde 100644
--- a/meson.build
+++ b/meson.build
@@ -2308,11 +2308,8 @@ config_host_data.set('CONFIG_PNG', png.found())
 config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
-if virgl.found()
-  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
-   cc.has_member('struct 
virgl_renderer_resource_info_ext', 'd3d_tex2d',
- prefix: '#include ',
- dependencies: virgl))
+if virgl.version().version_compare('>=1.0.0')
+  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.44.0




[PATCH v13 04/13] virtio-gpu: Unrealize GL device

2024-05-26 Thread Dmitry Osipenko
Even though GL GPU doesn't support hotplugging today, free virgl
resources when GL device is unrealized. For consistency.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 13 +
 hw/display/virtio-gpu-virgl.c  | 11 +++
 include/hw/virtio/virtio-gpu.h |  1 +
 3 files changed, 25 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 38a2b1bd3916..7978b2985e17 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -149,6 +149,18 @@ static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
+{
+VirtIOGPU *g = VIRTIO_GPU(qdev);
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
+
+if (gl->renderer_state >= RS_INITED) {
+virtio_gpu_virgl_deinit(g);
+}
+
+gl->renderer_state = RS_START;
+}
+
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -162,6 +174,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
void *data)
 vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
 
 vdc->realize = virtio_gpu_gl_device_realize;
+vdc->unrealize = virtio_gpu_gl_device_unrealize;
 vdc->reset = virtio_gpu_gl_reset;
 device_class_set_props(dc, virtio_gpu_gl_properties);
 }
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index fa0da8f5c7f1..66c4aab9b283 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -669,3 +669,14 @@ int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
 
 return capset2_max_ver ? 2 : 1;
 }
+
+void virtio_gpu_virgl_deinit(VirtIOGPU *g)
+{
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
+
+if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
+timer_free(gl->print_stats);
+}
+timer_free(gl->fence_poll);
+virgl_renderer_cleanup(NULL);
+}
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 6e71d799e5da..2faeda6f6abe 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -345,6 +345,7 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
+void virtio_gpu_virgl_deinit(VirtIOGPU *g);
 int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.44.0




[PATCH v13 08/13] virtio-gpu: Add virgl resource management

2024-05-26 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 4b2d4a643e30..8392d0fde984 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
&res_iovs,
&num_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs);
 }
 virgl_renderer_resource_unref(unref.resource_id);
+
+QTAILQ_REMOVE(&g->reslist, &res->base, next);
+
+g_free(res);
 }
 
 static void virgl_cmd_context_create(VirtIOGPU *g,
-- 
2.44.0




[PATCH v13 01/13] virtio-gpu: Move fence_poll timer to VirtIOGPUGL

2024-05-26 Thread Dmitry Osipenko
Move fence_poll timer to VirtIOGPUGL for consistency with cmdq_resume_bh
that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 8 +---
 include/hw/virtio/virtio-gpu.h | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9f34d0e6619c..7239a9f8e066 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -594,11 +594,12 @@ static void virtio_gpu_print_stats(void *opaque)
 static void virtio_gpu_fence_poll(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 virgl_renderer_poll();
 virtio_gpu_process_cmdq(g);
 if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
-timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
+timer_mod(gl->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
 }
 }
 
@@ -626,6 +627,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 {
 int ret;
 uint32_t flags = 0;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 if (qemu_egl_display) {
@@ -645,8 +647,8 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return ret;
 }
 
-g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- virtio_gpu_fence_poll, g);
+gl->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+  virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a7a..bc69fd78a440 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -196,7 +196,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *fence_poll;
 QEMUTimer *print_stats;
 
 uint32_t inflight;
@@ -231,6 +230,8 @@ struct VirtIOGPUGL {
 
 bool renderer_inited;
 bool renderer_reset;
+
+QEMUTimer *fence_poll;
 };
 
 struct VhostUserGPU {
-- 
2.44.0




Re: [PATCH v12 00/13] Support blob memory and venus on qemu

2024-05-26 Thread Dmitry Osipenko
On 5/27/24 02:46, Dmitry Osipenko wrote:
> On 5/22/24 12:00, Alex Bennée wrote:
>> Dmitry Osipenko  writes:
>>
>>> On 5/21/24 17:57, Alex Bennée wrote:
>>>> Alex Bennée  writes:
>>>>
>>>>> Dmitry Osipenko  writes:
>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> This series enables Vulkan Venus context support on virtio-gpu.
>>>>>>
>>>>>> All virglrender and almost all Linux kernel prerequisite changes
>>>>>> needed by Venus are already in upstream. For kernel there is a pending
>>>>>> KVM patchset that fixes mapping of compound pages needed for DRM drivers
>>>>>> using TTM [1], othewrwise hostmem blob mapping will fail with a KVM error
>>>>>> from Qemu.
>>>>>>
>>>>>> [1] 
>>>>>> https://lore.kernel.org/kvm/20240229025759.1187910-1-steve...@google.com/
>>>>>>
>>>>>> You'll need to use recent Mesa version containing patch that removes
>>>>>> dependency on cross-device feature from Venus that isn't supported by
>>>>>> Qemu [2].
>>>>>>
>>>>>> [2] 
>>>>>> https://gitlab.freedesktop.org/mesa/mesa/-/commit/087e9a96d13155e26987befae78b6ccbb7ae242b
>>>>>>
>>>>>> Example Qemu cmdline that enables Venus:
>>>>>>
>>>>>>   qemu-system-x86_64 -device 
>>>>>> virtio-vga-gl,hostmem=4G,blob=true,venus=true \
>>>>>>   -machine q35,accel=kvm,memory-backend=mem1 \
>>>>>>   -object memory-backend-memfd,id=mem1,size=8G -m 8G
>>>>>
>>>>> What is the correct device for non-x86 guests? We have virtio-gpu-gl-pci
>>>>> but when doing that I get:
>>>>>
>>>>>   -device virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true
>>>>>   qemu-system-aarch64: -device 
>>>>> virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true: opengl is not available
>>>>>
>>>>> According to 37f86af087 (virtio-gpu: move virgl realize + properties):
>>>>>
>>>>>   Drop the virgl property, the virtio-gpu-gl-device has virgl enabled no
>>>>>   matter what.  Just use virtio-gpu-device instead if you don't want
>>>>>   enable virgl and opengl.  This simplifies the logic and reduces the test
>>>>>   matrix.
>>>>>
>>>>> but that's not a good solution because that needs virtio-mmio and there
>>>>> are reasons to have a PCI device (for one thing no ambiguity about
>>>>> discovery).
>>>>
>>>> Oops my mistake forgetting:
>>>>
>>>>   --display gtk,gl=on
>>>>
>>>> Although I do see a lot of eglMakeContext failures.
>>>
>>> Please post the full Qemu cmdline you're using
>>
>> With:
>>
>>   ./qemu-system-aarch64 \
>>-machine type=virt,virtualization=on,pflash0=rom,pflash1=efivars \
>>-cpu neoverse-n1 \
>>-smp 4 \
>>-accel tcg \
>>-device virtio-net-pci,netdev=unet \
>>-device virtio-scsi-pci \
>>-device scsi-hd,drive=hd \
>>-netdev user,id=unet,hostfwd=tcp::-:22 \
>>-blockdev 
>> driver=raw,node-name=hd,file.driver=host_device,file.filename=/dev/zen-ssd2/trixie-arm64,discard=unmap
>>  \
>>-serial mon:stdio \
>>-blockdev 
>> node-name=rom,driver=file,filename=(pwd)/pc-bios/edk2-aarch64-code.fd,read-only=true
>>  \
>>-blockdev 
>> node-name=efivars,driver=file,filename=$HOME/images/qemu-arm64-efivars \
>>-m 8192 \
>>-object memory-backend-memfd,id=mem,size=8G,share=on \
>>-device virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true \
>>-display gtk,gl=on,show-cursor=on -vga none \
>>-device qemu-xhci -device usb-kbd -device usb-tablet
>>
>> I get a boot up with a lot of:
>>
>>  
>>  
>>
>>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed
>>  
>>  
>>
>>   (qemu:1

Re: [PATCH v12 00/13] Support blob memory and venus on qemu

2024-05-26 Thread Dmitry Osipenko
On 5/22/24 12:00, Alex Bennée wrote:
> I get a boot up with a lot of:
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed   
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed   
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed   
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed   

Have same problem with GTK and arm64/UEFI. Something is resetting
virtio-gpu device during boot (maybe UEFI fw) and it doesn't work
properly with GTK. I'd expect x86 should have same issue, but don't
recall x86 having it.

-- 
Best regards,
Dmitry




Re: [PATCH v12 03/13] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-05-26 Thread Dmitry Osipenko
On 5/22/24 15:48, Alex Bennée wrote:
>> New virglrerenderer features were stabilized with release of v1.0.0.
>> Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
>> with pre-release development versions of libvirglerender. Use virglrenderer
>> version to decide reliably which virgl features are available.
> Is the requirement for 087e9a96d13 (venus: make cross-device optional)
> on the host or guest side? Because I can't see its in a tagged version.

It's required only on guest side. Mesa 24.2 hasn't been tagged yet.

-- 
Best regards,
Dmitry




Re: [PATCH v12 00/13] Support blob memory and venus on qemu

2024-05-26 Thread Dmitry Osipenko
On 5/22/24 12:00, Alex Bennée wrote:
> Dmitry Osipenko  writes:
> 
>> On 5/21/24 17:57, Alex Bennée wrote:
>>> Alex Bennée  writes:
>>>
>>>> Dmitry Osipenko  writes:
>>>>
>>>>> Hello,
>>>>>
>>>>> This series enables Vulkan Venus context support on virtio-gpu.
>>>>>
>>>>> All virglrender and almost all Linux kernel prerequisite changes
>>>>> needed by Venus are already in upstream. For kernel there is a pending
>>>>> KVM patchset that fixes mapping of compound pages needed for DRM drivers
>>>>> using TTM [1], othewrwise hostmem blob mapping will fail with a KVM error
>>>>> from Qemu.
>>>>>
>>>>> [1] 
>>>>> https://lore.kernel.org/kvm/20240229025759.1187910-1-steve...@google.com/
>>>>>
>>>>> You'll need to use recent Mesa version containing patch that removes
>>>>> dependency on cross-device feature from Venus that isn't supported by
>>>>> Qemu [2].
>>>>>
>>>>> [2] 
>>>>> https://gitlab.freedesktop.org/mesa/mesa/-/commit/087e9a96d13155e26987befae78b6ccbb7ae242b
>>>>>
>>>>> Example Qemu cmdline that enables Venus:
>>>>>
>>>>>   qemu-system-x86_64 -device 
>>>>> virtio-vga-gl,hostmem=4G,blob=true,venus=true \
>>>>>   -machine q35,accel=kvm,memory-backend=mem1 \
>>>>>   -object memory-backend-memfd,id=mem1,size=8G -m 8G
>>>>
>>>> What is the correct device for non-x86 guests? We have virtio-gpu-gl-pci
>>>> but when doing that I get:
>>>>
>>>>   -device virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true
>>>>   qemu-system-aarch64: -device 
>>>> virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true: opengl is not available
>>>>
>>>> According to 37f86af087 (virtio-gpu: move virgl realize + properties):
>>>>
>>>>   Drop the virgl property, the virtio-gpu-gl-device has virgl enabled no
>>>>   matter what.  Just use virtio-gpu-device instead if you don't want
>>>>   enable virgl and opengl.  This simplifies the logic and reduces the test
>>>>   matrix.
>>>>
>>>> but that's not a good solution because that needs virtio-mmio and there
>>>> are reasons to have a PCI device (for one thing no ambiguity about
>>>> discovery).
>>>
>>> Oops my mistake forgetting:
>>>
>>>   --display gtk,gl=on
>>>
>>> Although I do see a lot of eglMakeContext failures.
>>
>> Please post the full Qemu cmdline you're using
> 
> With:
> 
>   ./qemu-system-aarch64 \
>-machine type=virt,virtualization=on,pflash0=rom,pflash1=efivars \
>-cpu neoverse-n1 \
>-smp 4 \
>-accel tcg \
>-device virtio-net-pci,netdev=unet \
>-device virtio-scsi-pci \
>-device scsi-hd,drive=hd \
>-netdev user,id=unet,hostfwd=tcp::-:22 \
>-blockdev 
> driver=raw,node-name=hd,file.driver=host_device,file.filename=/dev/zen-ssd2/trixie-arm64,discard=unmap
>  \
>-serial mon:stdio \
>-blockdev 
> node-name=rom,driver=file,filename=(pwd)/pc-bios/edk2-aarch64-code.fd,read-only=true
>  \
>-blockdev 
> node-name=efivars,driver=file,filename=$HOME/images/qemu-arm64-efivars \
>-m 8192 \
>-object memory-backend-memfd,id=mem,size=8G,share=on \
>-device virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true \
>-display gtk,gl=on,show-cursor=on -vga none \
>-device qemu-xhci -device usb-kbd -device usb-tablet
> 
> I get a boot up with a lot of:
> 
>   
>   
>  
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed 
>   
>
> 
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed 
>   
>
> 
>   (qemu:1545322): Gdk-WARNING **: 09:26:09.470: eglMakeCurrent failed 
>   
>
> 
>   (qemu:1545322): Gdk-

Re: [PATCH v12 13/13] virtio-gpu: Support Venus context

2024-05-23 Thread Dmitry Osipenko
On 5/23/24 10:18, Manos Pitsidianakis wrote:
>> #define virtio_gpu_hostmem_enabled(_cfg) \
>>     (_cfg.hostmem > 0)
>> +#define virtio_gpu_venus_enabled(_cfg) \
>> +    (_cfg.flags & (1 << VIRTIO_GPU_FLAG_VENUS_ENABLED))
>>
> 
> Can we have both venus and rutabaga enabled on the same virtio-gpu
> device? How would that work? It seems to me they should be mutually
> exclusive.

virtio-gpu-gl and virtio-gpu-rutabaga are separate device types. You
can't enable venus for rutabaga device because it doesn't support venus
and vice versa, Qemu will tell you that flag is invalid.

-- 
Best regards,
Dmitry




Re: [PATCH v12 10/13] virtio-gpu: Move fence_poll timer to VirtIOGPUGL

2024-05-21 Thread Dmitry Osipenko
On 5/20/24 06:51, Akihiko Odaki wrote:
> On 2024/05/20 6:27, Dmitry Osipenko wrote:
>> Move fence_poll timer to VirtIOGPUGL for consistency with cmdq_resume_bh
>> that are used only by GL device.
>>
>> Signed-off-by: Dmitry Osipenko 
> 
> Thanks for refacotoring.
> 
> Please move this before "[PATCH v12 01/13] virtio-gpu: Unrealize GL
> device" so that you don't have to rewrite code introduced by that patch.

I'll improve it all in v13, thank you for the review

-- 
Best regards,
Dmitry




Re: [PATCH v12 00/13] Support blob memory and venus on qemu

2024-05-21 Thread Dmitry Osipenko
On 5/21/24 17:57, Alex Bennée wrote:
> Alex Bennée  writes:
> 
>> Dmitry Osipenko  writes:
>>
>>> Hello,
>>>
>>> This series enables Vulkan Venus context support on virtio-gpu.
>>>
>>> All virglrender and almost all Linux kernel prerequisite changes
>>> needed by Venus are already in upstream. For kernel there is a pending
>>> KVM patchset that fixes mapping of compound pages needed for DRM drivers
>>> using TTM [1], othewrwise hostmem blob mapping will fail with a KVM error
>>> from Qemu.
>>>
>>> [1] 
>>> https://lore.kernel.org/kvm/20240229025759.1187910-1-steve...@google.com/
>>>
>>> You'll need to use recent Mesa version containing patch that removes
>>> dependency on cross-device feature from Venus that isn't supported by
>>> Qemu [2].
>>>
>>> [2] 
>>> https://gitlab.freedesktop.org/mesa/mesa/-/commit/087e9a96d13155e26987befae78b6ccbb7ae242b
>>>
>>> Example Qemu cmdline that enables Venus:
>>>
>>>   qemu-system-x86_64 -device virtio-vga-gl,hostmem=4G,blob=true,venus=true \
>>>   -machine q35,accel=kvm,memory-backend=mem1 \
>>>   -object memory-backend-memfd,id=mem1,size=8G -m 8G
>>
>> What is the correct device for non-x86 guests? We have virtio-gpu-gl-pci
>> but when doing that I get:
>>
>>   -device virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true
>>   qemu-system-aarch64: -device 
>> virtio-gpu-gl-pci,hostmem=4G,blob=true,venus=true: opengl is not available
>>
>> According to 37f86af087 (virtio-gpu: move virgl realize + properties):
>>
>>   Drop the virgl property, the virtio-gpu-gl-device has virgl enabled no
>>   matter what.  Just use virtio-gpu-device instead if you don't want
>>   enable virgl and opengl.  This simplifies the logic and reduces the test
>>   matrix.
>>
>> but that's not a good solution because that needs virtio-mmio and there
>> are reasons to have a PCI device (for one thing no ambiguity about
>> discovery).
> 
> Oops my mistake forgetting:
> 
>   --display gtk,gl=on
> 
> Although I do see a lot of eglMakeContext failures.

Please post the full Qemu cmdline you're using

-- 
Best regards,
Dmitry




[PATCH v12 07/13] virtio-gpu: Support blob scanout using dmabuf fd

2024-05-19 Thread Dmitry Osipenko
From: Robert Beckett 

Support displaying blob resources by handling SET_SCANOUT_BLOB
command.

Signed-by: Antonio Caggiano 
Signed-off-by: Robert Beckett 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 109 +
 hw/display/virtio-gpu.c|  12 ++--
 include/hw/virtio/virtio-gpu.h |   7 +++
 meson.build|   1 +
 4 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 612fa86e5f34..7d4d2882a5af 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 res->base.height = c2d.height;
 res->base.format = c2d.format;
 res->base.resource_id = c2d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c2d.resource_id;
@@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 res->base.height = c3d.height;
 res->base.format = c3d.format;
 res->base.resource_id = c3d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
 
 args.handle = c3d.resource_id;
@@ -509,6 +513,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
 g_free(resp);
 }
 
+#ifdef HAVE_VIRGL_RESOURCE_BLOB
+static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
+   struct virtio_gpu_ctrl_command *cmd)
+{
+struct virtio_gpu_framebuffer fb = { 0 };
+struct virgl_renderer_resource_info info;
+struct virtio_gpu_virgl_resource *res;
+struct virtio_gpu_set_scanout_blob ss;
+uint64_t fbend;
+
+VIRTIO_GPU_FILL_CMD(ss);
+virtio_gpu_scanout_blob_bswap(&ss);
+trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
+  ss.r.width, ss.r.height, ss.r.x,
+  ss.r.y);
+
+if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+  __func__, ss.scanout_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+return;
+}
+
+if (ss.resource_id == 0) {
+virtio_gpu_disable_scanout(g, ss.scanout_id);
+return;
+}
+
+if (ss.width < 16 ||
+ss.height < 16 ||
+ss.r.x + ss.r.width > ss.width ||
+ss.r.y + ss.r.height > ss.height) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
+  __func__, ss.scanout_id, ss.resource_id,
+  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
+  ss.width, ss.height);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (virgl_renderer_resource_get_info(ss.resource_id, &info)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have info %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (res->base.dmabuf_fd < 0) {
+res->base.dmabuf_fd = info.fd;
+}
+if (res->base.dmabuf_fd < 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource not backed by dmabuf 
%d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+fb.format = virtio_gpu_get_pixman_format(ss.format);
+if (!fb.format) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: pixel format not supported %d\n",
+  __func__, ss.format);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+fb.width = ss.width;
+fb.height = ss.height;
+fb.stride = ss.strides[0];
+fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
+
+fbend = fb.offset;
+fbend += fb.stride * (ss.r.height - 1);
+fbend += fb.b

[PATCH v12 11/13] virtio-gpu: Move print_stats timer to VirtIOGPUGL

2024-05-19 Thread Dmitry Osipenko
Move print_stats timer to VirtIOGPUGL for consistency with
cmdq_resume_bh and fence_poll that are used only by GL device.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 12 +++-
 include/hw/virtio/virtio-gpu.h |  2 +-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index c8b25a0f5d7c..a41c4f8e1cef 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1069,6 +1069,7 @@ static struct virgl_renderer_callbacks virtio_gpu_3d_cbs 
= {
 static void virtio_gpu_print_stats(void *opaque)
 {
 VirtIOGPU *g = opaque;
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 
 if (g->stats.requests) {
 fprintf(stderr, "stats: vq req %4d, %3d -- 3D %4d (%5d)\n",
@@ -1083,7 +1084,7 @@ static void virtio_gpu_print_stats(void *opaque)
 } else {
 fprintf(stderr, "stats: idle\r");
 }
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
+timer_mod(gl->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 static void virtio_gpu_fence_poll(void *opaque)
@@ -1146,9 +1147,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
   virtio_gpu_fence_poll, g);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
-  virtio_gpu_print_stats, g);
-timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 
1000);
+gl->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+   virtio_gpu_print_stats, g);
+timer_mod(gl->print_stats,
+  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000);
 }
 
 gl->cmdq_resume_bh = aio_bh_new(qemu_get_aio_context(),
@@ -1175,7 +1177,7 @@ void virtio_gpu_virgl_deinit(VirtIOGPU *g)
 qemu_bh_delete(gl->cmdq_resume_bh);
 
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
-timer_free(g->print_stats);
+timer_free(gl->print_stats);
 }
 timer_free(gl->fence_poll);
 virgl_renderer_cleanup(NULL);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 529c34481158..aea559cdacc5 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -195,7 +195,6 @@ struct VirtIOGPU {
 uint64_t hostmem;
 
 bool processing_cmdq;
-QEMUTimer *print_stats;
 
 uint32_t inflight;
 struct {
@@ -233,6 +232,7 @@ struct VirtIOGPUGL {
 
 QEMUBH *cmdq_resume_bh;
 QEMUTimer *fence_poll;
+QEMUTimer *print_stats;
 };
 
 struct VhostUserGPU {
-- 
2.44.0




[PATCH v12 02/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-05-19 Thread Dmitry Osipenko
virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
return code and don't execute virtio commands on error. Failed
virtio_gpu_virgl_init() will result in a timed out virtio commands
for a guest OS.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 15 +--
 hw/display/virtio-gpu-virgl.c  |  3 +++
 include/hw/virtio/virtio-gpu.h |  1 +
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 0c0a8d136954..b353c3193afa 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  struct virtio_gpu_scanout *s,
  uint32_t resource_id)
 {
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
 uint32_t width, height;
 uint32_t pixels, *data;
 
+if (!gl->renderer_inited) {
+return;
+}
+
 data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
 if (!data) {
 return;
@@ -60,13 +65,18 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, 
VirtQueue *vq)
 VirtIOGPU *g = VIRTIO_GPU(vdev);
 VirtIOGPUGL *gl = VIRTIO_GPU_GL(vdev);
 struct virtio_gpu_ctrl_command *cmd;
+int ret;
 
-if (!virtio_queue_ready(vq)) {
+if (!virtio_queue_ready(vq) || gl->renderer_init_failed) {
 return;
 }
 
 if (!gl->renderer_inited) {
-virtio_gpu_virgl_init(g);
+ret = virtio_gpu_virgl_init(g);
+if (ret) {
+gl->renderer_init_failed = true;
+return;
+}
 gl->renderer_inited = true;
 }
 if (gl->renderer_reset) {
@@ -101,6 +111,7 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
 if (gl->renderer_inited && !gl->renderer_reset) {
 virtio_gpu_virgl_reset_scanout(g);
 gl->renderer_reset = true;
+gl->renderer_init_failed = false;
 }
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 6ba4c24fda1d..bfbc6553e879 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -668,6 +668,9 @@ int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
 
 void virtio_gpu_virgl_deinit(VirtIOGPU *g)
 {
+if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
+timer_free(g->print_stats);
+}
 timer_free(g->fence_poll);
 virgl_renderer_cleanup(NULL);
 }
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 8ece1ec2e98b..236daba24dd2 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -230,6 +230,7 @@ struct VirtIOGPUGL {
 
 bool renderer_inited;
 bool renderer_reset;
+bool renderer_init_failed;
 };
 
 struct VhostUserGPU {
-- 
2.44.0




[PATCH v12 13/13] virtio-gpu: Support Venus context

2024-05-19 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 13 +
 include/hw/virtio/virtio-gpu.h |  3 +++
 meson.build|  1 +
 5 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index b8f395be8d2d..2078e74050bb 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -148,6 +148,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 70e2d28ba966..2e9862dd186a 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1130,6 +1130,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#ifdef VIRGL_RENDERER_VENUS
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, &virtio_gpu_3d_cbs);
 if (ret != 0) {
@@ -1161,7 +1166,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1170,12 +1175,21 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  &capset2_max_ver,
-  &capset2_max_size);
-if (capset2_max_ver) {
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   &capset_max_ver,
+   &capset_max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
 
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 052ab493a00b..0518bb858e88 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1491,6 +1491,19 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef HAVE_VIRGL_VENUS
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+}
+
 if (!virtio_gpu_base_device_realize(qdev,
 virtio_gpu_handle_ctrl_cb,
 virtio_gpu_handle_cursor_cb,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7e1fee836802..ec5d7517f141 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -99,6 +99,7 @@ enum virtio_gpu_base_conf_flags {
 VIRTIO_GPU_FLAG_BLOB_ENABLED,
 VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED,
 VIRTIO_GPU_FLAG_RUTABAGA_ENABLED,
+VIRTIO_GPU_FLAG_VENUS_ENABLED,
 };
 
 #define virtio_gpu_virgl_enabled(_cfg) \
@@ -117,6 +118,8 @@ enum virtio_gpu_base_conf_flags {
 (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED))
 #define virtio_gpu_hostmem_enabled(_cfg) \
 (_cfg.hostmem > 0)
+#define virtio_gpu_venus_enabled(_cfg) \
+(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VENUS_ENABLED))
 
 struct virtio_gpu_base_conf {
 uint32_t max_outputs;
diff --git a/meson.build b/meson.build
index 503a7736eda0..5a2b7b660c67 100644
--- a/meson.build
+++ b/meson.build
@@ -2305,6 +2305,7 @@ if virgl.version().version_compare('>=1.0.0')
   config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT&#

[PATCH v12 08/13] virtio-gpu: Support suspension of commands processing

2024-05-19 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 1e57a53d346c..6c8c7213bafa 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1054,6 +1054,11 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+break;
+}
+
 QTAILQ_REMOVE(&g->cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.44.0




[PATCH v12 09/13] virtio-gpu: Handle resource blob commands

2024-05-19 Thread Dmitry Osipenko
From: Antonio Caggiano 

Support BLOB resources creation, mapping and unmapping by calling the
new stable virglrenderer 0.10 interface. Only enabled when available and
via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 310 -
 hw/display/virtio-gpu.c|   4 +-
 include/hw/virtio/virtio-gpu.h |   2 +
 3 files changed, 312 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 7d4d2882a5af..63a5a983aad6 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -26,6 +26,18 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
+
+/*
+ * Used by virgl_cmd_resource_unref() to know whether async
+ * unmapping has been started.  Blob can be both mapped/unmapped
+ * on unref and we shouldn't unmap blob that wasn't mapped in the
+ * first place because it's a error condition.  This flag prevents
+ * performing step 3 of the async unmapping process described in the
+ * comment to virtio_gpu_virgl_async_unmap_resource_blob() if blob
+ * wasn't mapped in the first place on unref.
+ */
+bool async_unmap_in_progress;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -49,6 +61,128 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#ifdef HAVE_VIRGL_RESOURCE_BLOB
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+struct virtio_gpu_virgl_resource *res;
+};
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+VirtIOGPUGL *gl;
+
+vmr = container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+vmr->res->mr = NULL;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+gl = VIRTIO_GPU_GL(vmr->g);
+qemu_bh_schedule(gl->cmdq_resume_bh);
+g_free(vmr);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, &data, &size);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->res = res;
+vmr->g = g;
+
+mr = &vmr->mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(&b->hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_async_unmap_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource 
*res)
+{
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+int ret;
+
+/*
+ * Perform async unmapping in 3 steps:
+ *
+ * 1. Begin async unmapping with memory_region_del_subregion()
+ *and suspend/block cmd processing.
+ * 2. Wait for res->mr to be freed and cmd processing resumed
+ *asynchronously by virtio_gpu_virgl_hostmem_region_free().
+ * 3. Finish the unmapping with final virgl_renderer_resource_unmap().
+ */
+if (mr) {
+/* render will be unblocked once MR is freed */
+b->renderer_blocked++;
+
+/* memory region owns self res->mr object and frees it by itself */
+memory_region_set_enabled(m

[PATCH v12 06/13] virtio-gpu: Add virgl resource management

2024-05-19 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index fc667559cc41..612fa86e5f34 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(&g->reslist, &res->base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
&res_iovs,
&num_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs);
 }
 virgl_renderer_resource_unref(unref.resource_id);
+
+QTAILQ_REMOVE(&g->reslist, &res->base, next);
+
+g_free(res);
 }
 
 static void virgl_cmd_context_create(VirtIOGPU *g,
-- 
2.44.0




  1   2   3   4   5   >