diff options
| author | Jonah Palmer <jonah.palmer@oracle.com> | 2025-02-17 09:49:33 -0500 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2025-02-21 07:18:42 -0500 |
| commit | 05063f55841babae7216d36105440ed8ba632938 (patch) | |
| tree | 431b5199e4061f31fc623d9526d4c4747e4163df /hw/virtio/vhost-vdpa.c | |
| parent | 92cf61e70838c20adc82daa3170fdbb9d174b508 (diff) | |
| download | focaccia-qemu-05063f55841babae7216d36105440ed8ba632938.tar.gz focaccia-qemu-05063f55841babae7216d36105440ed8ba632938.zip | |
vhost-iova-tree, svq: Implement GPA->IOVA & partial IOVA->HVA trees
Creates and supports a GPA->IOVA tree and a partial IOVA->HVA tree by splitting up guest-backed memory maps and host-only memory maps from the full IOVA->HVA tree. That is, any guest-backed memory maps are now stored in the GPA->IOVA tree and host-only memory maps stay in the IOVA->HVA tree. Also propagates the GPAs (in_addr/out_addr) of a VirtQueueElement to vhost_svq_translate_addr() to translate GPAs to IOVAs via the GPA->IOVA tree (when descriptors are backed by guest memory). For descriptors backed by host-only memory, the existing partial SVQ IOVA->HVA tree is used. GPAs are unique in the guest's address space, ensuring unambiguous IOVA translations. This avoids the issue where different GPAs map to the same HVA, causing the original HVA->IOVA translation to potentially return an IOVA associated with the wrong intended GPA. Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com> Acked-by: Eugenio Pérez <eperezma@redhat.com> Message-Id: <20250217144936.3589907-3-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio/vhost-vdpa.c')
| -rw-r--r-- | hw/virtio/vhost-vdpa.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 703dcfc929..7efbde3d4c 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -360,17 +360,17 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, llsize = int128_sub(llend, int128_make64(iova)); if (s->shadow_data) { int r; - hwaddr hw_vaddr = (hwaddr)(uintptr_t)vaddr; + hwaddr gpa = section->offset_within_address_space; mem_region.size = int128_get64(llsize) - 1, mem_region.perm = IOMMU_ACCESS_FLAG(true, section->readonly), - r = vhost_iova_tree_map_alloc(s->iova_tree, &mem_region, hw_vaddr); + r = vhost_iova_tree_map_alloc_gpa(s->iova_tree, &mem_region, gpa); if (unlikely(r != IOVA_OK)) { error_report("Can't allocate a mapping (%d)", r); - if (mem_region.translated_addr == hw_vaddr) { - error_report("Insertion to IOVA->HVA tree failed"); + if (mem_region.translated_addr == gpa) { + error_report("Insertion to GPA->IOVA tree failed"); /* Remove the mapping from the IOVA-only tree */ goto fail_map; } @@ -392,7 +392,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, fail_map: if (s->shadow_data) { - vhost_iova_tree_remove(s->iova_tree, mem_region); + vhost_iova_tree_remove_gpa(s->iova_tree, mem_region); } fail: @@ -446,21 +446,18 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, if (s->shadow_data) { const DMAMap *result; - const void *vaddr = memory_region_get_ram_ptr(section->mr) + - section->offset_within_region + - (iova - section->offset_within_address_space); DMAMap mem_region = { - .translated_addr = (hwaddr)(uintptr_t)vaddr, + .translated_addr = section->offset_within_address_space, .size = int128_get64(llsize) - 1, }; - result = vhost_iova_tree_find_iova(s->iova_tree, &mem_region); + result = vhost_iova_tree_find_gpa(s->iova_tree, &mem_region); if (!result) { /* The memory listener map wasn't mapped */ return; } iova = result->iova; - vhost_iova_tree_remove(s->iova_tree, *result); + vhost_iova_tree_remove_gpa(s->iova_tree, *result); } vhost_vdpa_iotlb_batch_begin_once(s); /* |