diff options
author | Vivek Kasireddy <vivek.kasireddy@intel.com> | 2021-05-26 16:14:24 -0700 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2021-05-27 12:07:37 +0200 |
commit | e0933d91b1cdde2828955b02042e100dffd27399 (patch) | |
tree | c0909c1ac5a54e5cfa34a0127493659172df8e41 /hw/display/virtio-gpu.c | |
parent | cce386e19ebb44cdb3517b6969af558c6edd2090 (diff) |
virtio-gpu: Add virtio_gpu_resource_create_blob
This API allows Qemu to register the blob allocated by the Guest
as a new resource and map its backing storage.
Based-on-patch-by: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Message-Id: <20210526231429.1045476-10-vivek.kasireddy@intel.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/display/virtio-gpu.c')
-rw-r--r-- | hw/display/virtio-gpu.c | 73 |
1 files changed, 70 insertions, 3 deletions
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index f77a7fc7dd..788b4540d5 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -137,7 +137,7 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id, } if (require_backing) { - if (!res->iov || !res->image) { + if (!res->iov || (!res->image && !res->blob)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n", caller, resource_id); if (error) { @@ -313,6 +313,62 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, g->hostmem += res->hostmem; } +static void virtio_gpu_resource_create_blob(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_create_blob cblob; + int ret; + + VIRTIO_GPU_FILL_CMD(cblob); + virtio_gpu_create_blob_bswap(&cblob); + trace_virtio_gpu_cmd_res_create_blob(cblob.resource_id, cblob.size); + + if (cblob.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_find_resource(g, cblob.resource_id); + if (res) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n", + __func__, cblob.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + res = g_new0(struct virtio_gpu_simple_resource, 1); + res->resource_id = cblob.resource_id; + res->blob_size = cblob.size; + + if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_GUEST && + cblob.blob_flags != VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid memory type\n", + __func__); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + g_free(res); + return; + } + + if (res->iov) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; + } + + ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob), + cmd, &res->addrs, &res->iov, + &res->iov_cnt); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; + } + + virtio_gpu_init_udmabuf(res); + QTAILQ_INSERT_HEAD(&g->reslist, res, next); +} + static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id) { struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id]; @@ -390,7 +446,7 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g, res = virtio_gpu_find_check_resource(g, t2d.resource_id, true, __func__, &cmd->error); - if (!res) { + if (!res || res->blob) { return; } @@ -446,7 +502,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, res = virtio_gpu_find_check_resource(g, rf.resource_id, false, __func__, &cmd->error); - if (!res) { + if (!res || res->blob) { return; } @@ -715,6 +771,10 @@ static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, res->iov_cnt = 0; g_free(res->addrs); res->addrs = NULL; + + if (res->blob) { + virtio_gpu_fini_udmabuf(res); + } } static void @@ -785,6 +845,13 @@ void virtio_gpu_simple_process_cmd(VirtIOGPU *g, case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: virtio_gpu_resource_create_2d(g, cmd); break; + case VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB: + if (!virtio_gpu_blob_enabled(g->parent_obj.conf)) { + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + break; + } + virtio_gpu_resource_create_blob(g, cmd); + break; case VIRTIO_GPU_CMD_RESOURCE_UNREF: virtio_gpu_resource_unref(g, cmd); break; |