On Wed, Feb 5, 2025 at 3:58 PM Jonah Palmer <jonah.pal...@oracle.com> wrote:
>
> An issue arises from aliased memory mappings in the guest, where
> different GPAs map to the same HVA. For example:
>
>  - GPA1->HVA1
>  - GPA2->HVA1
>
> When these mappings exist in the IOVA->HVA tree, a lookup by an HVA
> backed by guest memory results in ambiguities because the same HVA could
> correspond to multiple GPAs. This duplication causes issues in managing
> IOVA trees for SVQs in vDPA, leading to incorrect behavior.
>
> For example, consider these mapped guest memory regions:
>
>               HVA                            GPA                         IOVA
> -------------------------------  --------------------------- 
> ----------------------------
> [0x7f7903e00000, 0x7f7983e00000) [0x0, 0x80000000)           [0x1000, 
> 0x80000000)
> [0x7f7983e00000, 0x7f9903e00000) [0x100000000, 0x2080000000) [0x80001000, 
> 0x2000001000)
> [0x7f7903ea0000, 0x7f7903ec0000) [0xfeda0000, 0xfedc0000)    [0x2000001000, 
> 0x2000021000)
>
> The last HVA range [0x7f7903ea0000, 0x7f7903ec0000) is contained within
> the first HVA range [0x7f7903e00000, 0x7f7983e00000). Despite this, the
> GPA ranges for the first and third mappings do not overlap, so the guest
> sees them as distinct physical memory regions.
>
> Now consider an operation to unmap the mapping associated with HVA
> 0x7f7903eb0000. This HVA fits into both the first and third HVA ranges.
>
> When searching the HVA->IOVA tree, the search stops at the first
> matching HVA range [0x7f7903e00000, 0x7f7983e00000) due to the behavior
> of the red-black tree (GTree). However, the correct mapping to remove is
> the third mappings, as the HVA translate to GPA 0xfedb0000, which only
> fits in the third mapping's GPA range.
>
> To address this, we implement a GPA->IOVA tree and use the GPAs of
> descriptors backed by guest memory when translating to IOVA.
>
> When a descriptor's GPA is used for translation, the GPA->IOVA tree
> ensures that each GPA maps to exactly one IOVA, regardless of any
> overlapping HVAs. This guarantees that operations such as unmapping or
> accessing a descriptor correctly targets the intended memory region in
> the guest's address space.
>
> For descriptors not backed by guest memory, the existing IOVA->HVA tree
> is still used.
>
> GPAs are unique and non-overlapping within the guest's address space. By
> translating GPAs to IOVAs, the ambiguity caused by multiple GPAs mapping
> to the same HVA is avoided.
>

I'd squash patches 2 and 3. While it adds some clarification, I think
it is not worth adding the code to remove it.

Either way,

Acked-by: Eugenio Pérez <epere...@redhat.com>

Thanks!

> --------
> This series is a different approach of [1] and is based off of [2],
> where this issue was originally discovered.
>
> Patch v1:
> ---------
>  * Created separate alloc functions for guest-backed and host-only
>    memory.
>  * Alloc functions also insert mappings to their respective trees.
>  * Make patches self-contained and functional to prevent breakage during
>    bisection.
>  * Don't move range checks from alloc functions.
>  * Use existing VirtQueueElement members 'in_addr' & 'out_addr' instead
>    of creating custom 'in_xlat_addr' & 'out_xlat_addr' members.
>  * Move documentation changes to separate patch.
>
> RFC v3:
> -------
>  * Decouple the IOVA allocator to support a SVQ IOVA->HVA tree for
>    host-only mappings.
>  * Move range check for IOVA allocator to its own patch.
>  * Implement a GPA->IOVA tree alongside the SVQ IOVA->HVA & IOVA-only
>    trees.
>  * Add in_xlat_addr & out_xlat_addr VirtQueueElement members to hold the
>    GPAs of an element's input/output descriptors (to be used during
>    translation).
>
> RFC v2:
> -------
>  * Don't decouple IOVA allocator.
>  * Build a IOVA->GPA tree (instead of GPA->IOVA tree).
>  * Remove IOVA-only tree and keep the full IOVA->HVA tree.
>  * Only search through RAMBlocks when we know the HVA is backed by
>    guest memory.
>  * Slight rewording of function names.
>
> RFC v1:
> -------
>  * Alternative approach of [1].
>  * First attempt to address this issue found in [2].
>
> [1] 
> https://lore.kernel.org/qemu-devel/20240410100345.389462-1-epere...@redhat.com
> [2] 
> https://lore.kernel.org/qemu-devel/20240201180924.487579-1-epere...@redhat.com
>
> Jonah Palmer (4):
>   vhost-iova-tree: Implement an IOVA-only tree
>   vhost-iova-tree: Implement GPA->IOVA & partial IOVA->HVA trees
>   svq: Support translations via GPAs in vhost_svq_translate_addr
>   vhost-iova-tree: Update documentation
>
>  hw/virtio/vhost-iova-tree.c        | 115 ++++++++++++++++++++++++-----
>  hw/virtio/vhost-iova-tree.h        |   8 +-
>  hw/virtio/vhost-shadow-virtqueue.c |  55 +++++++++-----
>  hw/virtio/vhost-shadow-virtqueue.h |   5 +-
>  hw/virtio/vhost-vdpa.c             |  40 ++++++----
>  include/qemu/iova-tree.h           |  22 ++++++
>  net/vhost-vdpa.c                   |  12 ++-
>  util/iova-tree.c                   |  46 ++++++++++++
>  8 files changed, 248 insertions(+), 55 deletions(-)
>
> --
> 2.43.5
>


Reply via email to