aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/display/virtio-gpu-3d.c7
-rw-r--r--hw/display/virtio-gpu.c76
-rw-r--r--include/hw/virtio/virtio-gpu.h3
3 files changed, 52 insertions, 34 deletions
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index d989648..72c14d9 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -283,22 +283,23 @@ static void virgl_resource_attach_backing(VirtIOGPU *g,
{
struct virtio_gpu_resource_attach_backing att_rb;
struct iovec *res_iovs;
+ uint32_t res_niov;
int ret;
VIRTIO_GPU_FILL_CMD(att_rb);
trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
- ret = virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs);
+ ret = virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs, &res_niov);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
}
ret = virgl_renderer_resource_attach_iov(att_rb.resource_id,
- res_iovs, att_rb.nr_entries);
+ res_iovs, res_niov);
if (ret != 0)
- virtio_gpu_cleanup_mapping_iov(g, res_iovs, att_rb.nr_entries);
+ virtio_gpu_cleanup_mapping_iov(g, res_iovs, res_niov);
}
static void virgl_resource_detach_backing(VirtIOGPU *g,
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index c9f5e36..6f3791d 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -608,11 +608,12 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
- uint64_t **addr, struct iovec **iov)
+ uint64_t **addr, struct iovec **iov,
+ uint32_t *niov)
{
struct virtio_gpu_mem_entry *ents;
size_t esize, s;
- int i;
+ int e, v;
if (ab->nr_entries > 16384) {
qemu_log_mask(LOG_GUEST_ERROR,
@@ -633,37 +634,53 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
return -1;
}
- *iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
+ *iov = NULL;
if (addr) {
- *addr = g_malloc0(sizeof(uint64_t) * ab->nr_entries);
+ *addr = NULL;
}
- for (i = 0; i < ab->nr_entries; i++) {
- uint64_t a = le64_to_cpu(ents[i].addr);
- uint32_t l = le32_to_cpu(ents[i].length);
- hwaddr len = l;
- (*iov)[i].iov_base = dma_memory_map(VIRTIO_DEVICE(g)->dma_as,
- a, &len, DMA_DIRECTION_TO_DEVICE);
- (*iov)[i].iov_len = len;
- if (addr) {
- (*addr)[i] = a;
- }
- if (!(*iov)[i].iov_base || len != l) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
- " resource %d element %d\n",
- __func__, ab->resource_id, i);
- if ((*iov)[i].iov_base) {
- i++; /* cleanup the 'i'th map */
+ for (e = 0, v = 0; e < ab->nr_entries; e++) {
+ uint64_t a = le64_to_cpu(ents[e].addr);
+ uint32_t l = le32_to_cpu(ents[e].length);
+ hwaddr len;
+ void *map;
+
+ do {
+ len = l;
+ map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as,
+ a, &len, DMA_DIRECTION_TO_DEVICE);
+ if (!map) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
+ " resource %d element %d\n",
+ __func__, ab->resource_id, e);
+ virtio_gpu_cleanup_mapping_iov(g, *iov, v);
+ g_free(ents);
+ *iov = NULL;
+ if (addr) {
+ g_free(*addr);
+ *addr = NULL;
+ }
+ return -1;
+ }
+
+ if (!(v % 16)) {
+ *iov = g_realloc(*iov, sizeof(struct iovec) * (v + 16));
+ if (addr) {
+ *addr = g_realloc(*addr, sizeof(uint64_t) * (v + 16));
+ }
}
- virtio_gpu_cleanup_mapping_iov(g, *iov, i);
- g_free(ents);
- *iov = NULL;
+ (*iov)[v].iov_base = map;
+ (*iov)[v].iov_len = len;
if (addr) {
- g_free(*addr);
- *addr = NULL;
+ (*addr)[v] = a;
}
- return -1;
- }
+
+ a += len;
+ l -= len;
+ v += 1;
+ } while (l > 0);
}
+ *niov = v;
+
g_free(ents);
return 0;
}
@@ -717,13 +734,12 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
return;
}
- ret = virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs, &res->iov);
+ ret = virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs,
+ &res->iov, &res->iov_cnt);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
}
-
- res->iov_cnt = ab.nr_entries;
}
static void
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index fae1492..0d15af4 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -209,7 +209,8 @@ void virtio_gpu_get_edid(VirtIOGPU *g,
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
- uint64_t **addr, struct iovec **iov);
+ uint64_t **addr, struct iovec **iov,
+ uint32_t *niov);
void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,
struct iovec *iov, uint32_t count);
void virtio_gpu_process_cmdq(VirtIOGPU *g);