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 add the offset to the pointer returned from memory_region_get_ram_ptr() to obtain the host address. Note that we take a reference on the memory region but we would still eventually call dma_memory_unmap() (to unref the mr). 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 | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 199b18c746..d746c5f426 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -798,6 +798,23 @@ 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; + 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(mr)) { + memory_region_ref(mr); + return memory_region_get_ram_ptr(mr) + xlat; + } + return NULL; +} + int virtio_gpu_create_mapping_iov(VirtIOGPU *g, uint32_t nr_entries, uint32_t offset, struct virtio_gpu_ctrl_command *cmd, @@ -839,9 +856,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
