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>
This commit is contained in:
Vivek Kasireddy 2021-05-26 16:14:24 -07:00 committed by Gerd Hoffmann
parent cce386e19e
commit e0933d91b1
3 changed files with 80 additions and 3 deletions

View File

@ -32,6 +32,7 @@ virtio_gpu_cmd_get_edid(uint32_t scanout) "scanout %d"
virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d" virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d" virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d"
virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d" virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d"
virtio_gpu_cmd_res_create_blob(uint32_t res, uint64_t size) "res 0x%x, size %" PRId64
virtio_gpu_cmd_res_unref(uint32_t res) "res 0x%x" virtio_gpu_cmd_res_unref(uint32_t res) "res 0x%x"
virtio_gpu_cmd_res_back_attach(uint32_t res) "res 0x%x" virtio_gpu_cmd_res_back_attach(uint32_t res) "res 0x%x"
virtio_gpu_cmd_res_back_detach(uint32_t res) "res 0x%x" virtio_gpu_cmd_res_back_detach(uint32_t res) "res 0x%x"

View File

@ -137,7 +137,7 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
} }
if (require_backing) { 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", qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n",
caller, resource_id); caller, resource_id);
if (error) { if (error) {
@ -313,6 +313,62 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
g->hostmem += res->hostmem; 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) static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
{ {
struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[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, res = virtio_gpu_find_check_resource(g, t2d.resource_id, true,
__func__, &cmd->error); __func__, &cmd->error);
if (!res) { if (!res || res->blob) {
return; return;
} }
@ -446,7 +502,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
res = virtio_gpu_find_check_resource(g, rf.resource_id, false, res = virtio_gpu_find_check_resource(g, rf.resource_id, false,
__func__, &cmd->error); __func__, &cmd->error);
if (!res) { if (!res || res->blob) {
return; return;
} }
@ -715,6 +771,10 @@ static void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
res->iov_cnt = 0; res->iov_cnt = 0;
g_free(res->addrs); g_free(res->addrs);
res->addrs = NULL; res->addrs = NULL;
if (res->blob) {
virtio_gpu_fini_udmabuf(res);
}
} }
static void static void
@ -785,6 +845,13 @@ void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
virtio_gpu_resource_create_2d(g, cmd); virtio_gpu_resource_create_2d(g, cmd);
break; 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: case VIRTIO_GPU_CMD_RESOURCE_UNREF:
virtio_gpu_resource_unref(g, cmd); virtio_gpu_resource_unref(g, cmd);
break; break;

View File

@ -59,4 +59,13 @@ virtio_gpu_t2d_bswap(struct virtio_gpu_transfer_to_host_2d *t2d)
le32_to_cpus(&t2d->padding); le32_to_cpus(&t2d->padding);
} }
static inline void
virtio_gpu_create_blob_bswap(struct virtio_gpu_resource_create_blob *cblob)
{
virtio_gpu_ctrl_hdr_bswap(&cblob->hdr);
le32_to_cpus(&cblob->resource_id);
le32_to_cpus(&cblob->blob_flags);
le64_to_cpus(&cblob->size);
}
#endif #endif