On Thu, Apr 01, 2021 at 04:34:37PM +0100, Robin Murphy wrote: > On 2021-03-31 04:00, Isaac J. Manjarres wrote: > > The IOMMU framework currently unmaps memory one page block at a time, > > per the page block sizes that are supported by the IOMMU hardware. > > Now that IOMMU drivers can supply a callback for unmapping multiple > > in one call, add support in the IOMMU framework to calculate how many > > page mappings of the same size can be unmapped in one shot, and invoke the > > IOMMU driver's unmap_pages callback if it has one. Otherwise, the > > existing behavior will be used. > > > > Signed-off-by: Isaac J. Manjarres <isa...@codeaurora.org> > > Suggested-by: Will Deacon <w...@kernel.org> > > --- > > drivers/iommu/iommu.c | 44 +++++++++++++++++++++++++++++++++++++------ > > 1 file changed, 38 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > > index d0b0a15dba84..dc4295f6bc7f 100644 > > --- a/drivers/iommu/iommu.c > > +++ b/drivers/iommu/iommu.c > > @@ -2356,8 +2356,8 @@ phys_addr_t iommu_iova_to_phys(struct iommu_domain > > *domain, dma_addr_t iova) > > } > > EXPORT_SYMBOL_GPL(iommu_iova_to_phys); > > -static size_t iommu_pgsize(struct iommu_domain *domain, > > - unsigned long addr_merge, size_t size) > > +static size_t __iommu_pgsize(struct iommu_domain *domain, > > + unsigned long addr_merge, size_t size) > > { > > unsigned int pgsize_idx; > > size_t pgsize; > > @@ -2388,6 +2388,24 @@ static size_t iommu_pgsize(struct iommu_domain > > *domain, > > return pgsize; > > } > > +static size_t iommu_pgsize(struct iommu_domain *domain, > > + unsigned long addr_merge, size_t size, > > + size_t *pgcount) > > +{ > > + size_t pgsize = __iommu_pgsize(domain, addr_merge, size); > > + size_t pgs = 0; > > + > > + do { > > + pgs++; > > + size -= pgsize; > > + addr_merge += pgsize; > > + } while (size && __iommu_pgsize(domain, addr_merge, size) == pgsize); > > This looks horrifically inefficient. As part of calculating the best current > page size it should then be pretty trivial to calculate "(size & > next_pgsize_up - 1) >> pgsize_idx" for the number of current-size pages up > to the next-better-size boundary (with next_pgsize_up being 0 if pgsize is > already the largest possible for the relative alignment of physical and > virtual address). A loop is just... yuck :(
Hehe, I'm glad you said that as I was thinking the same thing. It's surprisingly fiddly to get this right, but I spent some time hacking it today and I _think_ I have something that Isaac could build on (and hopefully won't be too hairy for ->map either). I'll post it as an RFC in a sec... Will _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu