qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-arm] [PATCH for-4.2 v10 08/15] virtio-iommu: Implement map/unm


From: Tian, Kevin
Subject: Re: [Qemu-arm] [PATCH for-4.2 v10 08/15] virtio-iommu: Implement map/unmap
Date: Wed, 4 Sep 2019 04:23:50 +0000

> From: Peter Xu [mailto:address@hidden]
> Sent: Wednesday, September 4, 2019 9:44 AM
> 
> On Tue, Sep 03, 2019 at 01:37:11PM +0200, Auger Eric wrote:
> > Hi Peter,
> >
> > On 8/19/19 10:11 AM, Peter Xu wrote:
> > > On Tue, Jul 30, 2019 at 07:21:30PM +0200, Eric Auger wrote:
> > >
> > > [...]
> > >
> > >> +    mapping = g_tree_lookup(domain->mappings, (gpointer)(&interval));
> > >> +
> > >> +    while (mapping) {
> > >> +        viommu_interval current;
> > >> +        uint64_t low  = mapping->virt_addr;
> > >> +        uint64_t high = mapping->virt_addr + mapping->size - 1;
> > >> +
> > >> +        current.low = low;
> > >> +        current.high = high;
> > >> +
> > >> +        if (low == interval.low && size >= mapping->size) {
> > >> +            g_tree_remove(domain->mappings, (gpointer)(&current));
> > >> +            interval.low = high + 1;
> > >> +            trace_virtio_iommu_unmap_left_interval(current.low,
> current.high,
> > >> +                interval.low, interval.high);
> > >> +        } else if (high == interval.high && size >= mapping->size) {
> > >> +            trace_virtio_iommu_unmap_right_interval(current.low,
> current.high,
> > >> +                interval.low, interval.high);
> > >> +            g_tree_remove(domain->mappings, (gpointer)(&current));
> > >> +            interval.high = low - 1;
> > >> +        } else if (low > interval.low && high < interval.high) {
> > >> +            trace_virtio_iommu_unmap_inc_interval(current.low,
> current.high);
> > >> +            g_tree_remove(domain->mappings, (gpointer)(&current));
> > >> +        } else {
> > >> +            break;
> > >> +        }
> > >> +        if (interval.low >= interval.high) {
> > >> +            return VIRTIO_IOMMU_S_OK;
> > >> +        } else {
> > >> +            mapping = g_tree_lookup(domain->mappings,
> (gpointer)(&interval));
> > >> +        }
> > >> +    }
> > >> +
> > >> +    if (mapping) {
> > >> +        qemu_log_mask(LOG_GUEST_ERROR,
> > >> +                      "****** %s: Unmap 0x%"PRIx64" size=0x%"PRIx64
> > >> +                     " from 0x%"PRIx64" size=0x%"PRIx64" is not 
> > >> supported\n",
> > >> +                     __func__, interval.low, size,
> > >> +                     mapping->virt_addr, mapping->size);
> > >> +    } else {
> > >> +        return VIRTIO_IOMMU_S_OK;
> > >> +    }
> > >> +
> > >> +    return VIRTIO_IOMMU_S_INVAL;
> > >
> > > Could the above chunk be simplified as something like below?
> > >
> > >   while ((mapping = g_tree_lookup(domain->mappings, &interval))) {
> > >     g_tree_remove(domain->mappings, mapping);
> > >   }
> > Indeed the code could be simplified. I only need to make sure I don't
> > split an existing mapping.
> 
> Hmm... Do we need to still split an existing mapping if necessary?
> For example when with this mapping:
> 
>   iova=0x1000, size=0x2000, phys=ADDR1, flags=FLAGS1
> 
> And if we want to unmap the range (iova=0, size=0x2000), then we
> should split the existing mappping and leave this one:
> 
>   iova=0x2000, size=0x1000, phys=(ADDR1+0x1000), flags=FLAGS1
> 
> Right?
> 

virtio-iommu spec explicitly disallows partial unmap.

5.11.6.6.1 Driver Requirements: UNMAP request

The first address of a range MUST either be the first address of a 
mapping or be outside any mapping. The last address of a range 
MUST either be the last address of a mapping or be outside any 
mapping.

5.11.6.6.2 Device Requirements: UNMAP request

If a mapping affected by the range is not covered in its entirety 
by the range (the UNMAP request would split the mapping), 
then the device SHOULD set the request status to VIRTIO_IOMMU
_S_RANGE, and SHOULD NOT remove any mapping.

Thanks
Kevin

reply via email to

[Prev in Thread] Current Thread [Next in Thread]