diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index 23f39de94d..b13ced38fa 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -291,8 +291,11 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, return; } - virgl_renderer_resource_attach_iov(att_rb.resource_id, - res_iovs, att_rb.nr_entries); + ret = virgl_renderer_resource_attach_iov(att_rb.resource_id, + res_iovs, att_rb.nr_entries); + + if (ret != 0) + virtio_gpu_cleanup_mapping_iov(res_iovs, att_rb.nr_entries); } static void virgl_resource_detach_backing(VirtIOGPU *g, @@ -371,8 +374,12 @@ static void virgl_cmd_get_capset(VirtIOGPU *g, virgl_renderer_get_cap_set(gc.capset_id, &max_ver, &max_size); - resp = g_malloc(sizeof(*resp) + max_size); + if (!max_size) { + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + resp = g_malloc(sizeof(*resp) + max_size); resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET; virgl_renderer_fill_caps(gc.capset_id, gc.capset_version, diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 5f32e1aae9..ca88cf478d 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -28,6 +28,8 @@ static struct virtio_gpu_simple_resource* virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); +static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res); + #ifdef CONFIG_VIRGL #include #define VIRGL(_g, _virgl, _simple, ...) \ @@ -338,10 +340,14 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; return; } - res->image = pixman_image_create_bits(pformat, - c2d.width, - c2d.height, - NULL, 0); + + res->hostmem = PIXMAN_FORMAT_BPP(pformat) * c2d.width * c2d.height; + if (res->hostmem + g->hostmem < g->conf.max_hostmem) { + res->image = pixman_image_create_bits(pformat, + c2d.width, + c2d.height, + NULL, 0); + } if (!res->image) { qemu_log_mask(LOG_GUEST_ERROR, @@ -353,13 +359,16 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, } QTAILQ_INSERT_HEAD(&g->reslist, res, next); + g->hostmem += res->hostmem; } static void virtio_gpu_resource_destroy(VirtIOGPU *g, struct virtio_gpu_simple_resource *res) { pixman_image_unref(res->image); + virtio_gpu_cleanup_mapping(res); QTAILQ_REMOVE(&g->reslist, res, next); + g->hostmem -= res->hostmem; g_free(res); } @@ -705,6 +714,11 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g, return; } + if (res->iov) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; + } + ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov); if (ret != 0) { cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; @@ -1241,6 +1255,8 @@ static const VMStateDescription vmstate_virtio_gpu = { static Property virtio_gpu_properties[] = { DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1), + DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf.max_hostmem, + 256 * 1024 * 1024), #ifdef CONFIG_VIRGL DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags, VIRTIO_GPU_FLAG_VIRGL_ENABLED, true), diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 20d1cd683a..f3a98a3261 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -38,6 +38,7 @@ struct virtio_gpu_simple_resource { unsigned int iov_cnt; uint32_t scanout_bitmask; pixman_image_t *image; + uint64_t hostmem; QTAILQ_ENTRY(virtio_gpu_simple_resource) next; }; @@ -68,6 +69,7 @@ enum virtio_gpu_conf_flags { (_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED)) struct virtio_gpu_conf { + uint64_t max_hostmem; uint32_t max_outputs; uint32_t flags; }; @@ -103,6 +105,7 @@ typedef struct VirtIOGPU { struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS]; struct virtio_gpu_conf conf; + uint64_t hostmem; int enabled_output_bitmask; struct virtio_gpu_config virtio_config;