If the Guest provides a DMA address that is associated with a ram device (such as a PCI device region and not its system memory), then we can obtain the hva (host virtual address) by invoking address_space_translate() followed by memory_region_get_ram_ptr().
This is because the ram device's address space is not accessible to virtio-gpu directly and hence dma_memory_map() cannot be used. Therefore, we first need to identify the memory region associated with the DMA address and figure out if it belongs to a ram device or not and decide how to obtain the host address accordingly. Note that we take a reference on the memory region if it belongs to a ram device but we would still call dma_memory_unmap() later (to unref mr) regardless of how we obtained the hva. Cc: Marc-André Lureau <[email protected]> Cc: Alex Bennée <[email protected]> Cc: Akihiko Odaki <[email protected]> Cc: Dmitry Osipenko <[email protected]> Cc: Alex Williamson <[email protected]> Cc: Cédric Le Goater <[email protected]> Signed-off-by: Vivek Kasireddy <[email protected]> --- hw/display/virtio-gpu.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 199b18c746..d352b5afd6 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -798,6 +798,26 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g, &fb, res, &ss.r, &cmd->error); } +static void *virtio_gpu_dma_memory_map(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd, + uint64_t a, hwaddr *len) +{ + MemoryRegion *mr = NULL; + hwaddr xlat; + + mr = address_space_translate(VIRTIO_DEVICE(g)->dma_as, a, &xlat, len, + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); + if (memory_region_is_ram_device(mr)) { + memory_region_ref(mr); + return memory_region_get_ram_ptr(mr) + xlat; + } + + return dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, len, + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); +} + int virtio_gpu_create_mapping_iov(VirtIOGPU *g, uint32_t nr_entries, uint32_t offset, struct virtio_gpu_ctrl_command *cmd, @@ -839,9 +859,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, do { len = l; - map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len, - DMA_DIRECTION_TO_DEVICE, - MEMTXATTRS_UNSPECIFIED); + map = virtio_gpu_dma_memory_map(g, cmd, a, &len); if (!map) { qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" " element %d\n", __func__, e); -- 2.50.1
