aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/display/virtio-gpu-3d.c13
-rw-r--r--hw/display/virtio-gpu.c24
-rw-r--r--include/hw/virtio/virtio-gpu.h3
3 files changed, 33 insertions, 7 deletions
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 <virglrenderer.h>
#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;