Blob unmapping may be suspended because of remaining uses of the
mapping. virtio_gpu_process_cmdq() uses the following condition to
detect a suspended command:
!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)
However, the guest may set VIRTIO_GPU_FLAG_FENCE for a command that
performs blob unmapping. Such a command will be incorrectly assumed
as not being suspended. Add a dedicated flag for the suspended state
to avoid overloading VIRTIO_GPU_FLAG_FENCE.
Fixes: 640f9149c3dc ("virtio-gpu: Support suspension of commands processing")
Signed-off-by: Akihiko Odaki <[email protected]>
---
include/hw/virtio/virtio-gpu.h | 1 +
hw/display/virtio-gpu-virgl.c | 17 +++++++----------
hw/display/virtio-gpu.c | 5 ++---
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 9404e488208a..3eccc4bc39c3 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -141,6 +141,7 @@ struct virtio_gpu_ctrl_command {
struct virtio_gpu_ctrl_hdr cmd_hdr;
uint32_t error;
bool finished;
+ bool suspended;
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9bda572426b2..c37df91e3ed1 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -440,8 +440,7 @@ virtio_gpu_virgl_resource_unref(VirtIOGPU *g,
}
static void virgl_cmd_resource_unref(VirtIOGPU *g,
- struct virtio_gpu_ctrl_command *cmd,
- bool *cmd_suspended)
+ struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_resource_unref unref;
struct virtio_gpu_virgl_resource *res;
@@ -457,7 +456,7 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
return;
}
- virtio_gpu_virgl_resource_unref(g, res, cmd_suspended);
+ virtio_gpu_virgl_resource_unref(g, res, &cmd->suspended);
}
void virtio_gpu_virgl_resource_destroy(VirtIOGPU *g,
@@ -946,8 +945,7 @@ static void virgl_cmd_resource_map_blob(VirtIOGPU *g,
}
static void virgl_cmd_resource_unmap_blob(VirtIOGPU *g,
- struct virtio_gpu_ctrl_command *cmd,
- bool *cmd_suspended)
+ struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_resource_unmap_blob ublob;
struct virtio_gpu_virgl_resource *res;
@@ -964,7 +962,7 @@ static void virgl_cmd_resource_unmap_blob(VirtIOGPU *g,
return;
}
- ret = virtio_gpu_virgl_unmap_resource_blob(g, res, cmd_suspended);
+ ret = virtio_gpu_virgl_unmap_resource_blob(g, res, &cmd->suspended);
if (ret) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -1036,7 +1034,6 @@ static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
- bool cmd_suspended = false;
int ret;
VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
@@ -1080,7 +1077,7 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
virgl_cmd_resource_flush(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_UNREF:
- virgl_cmd_resource_unref(g, cmd, &cmd_suspended);
+ virgl_cmd_resource_unref(g, cmd);
break;
case VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE:
/* TODO add security */
@@ -1110,7 +1107,7 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
virgl_cmd_resource_map_blob(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB:
- virgl_cmd_resource_unmap_blob(g, cmd, &cmd_suspended);
+ virgl_cmd_resource_unmap_blob(g, cmd);
break;
case VIRTIO_GPU_CMD_SET_SCANOUT_BLOB:
virgl_cmd_set_scanout_blob(g, cmd);
@@ -1121,7 +1118,7 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
break;
}
- if (cmd_suspended || cmd->finished) {
+ if (cmd->suspended || cmd->finished) {
return;
}
if (cmd->error) {
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d520f69e6453..dd6c09d1ddcf 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1193,11 +1193,10 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
break;
}
- /* process command */
+ cmd->suspended = false;
vgc->process_cmd(g, cmd);
- /* command suspended */
- if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+ if (cmd->suspended) {
trace_virtio_gpu_cmd_suspended(cmd->cmd_hdr.type);
break;
}
--
2.55.0