On 2026-06-29 at 11:49:56 +0100, Robin Murphy wrote:
> On 29/06/2026 11:12 am, Krzysztof Karas wrote:
> > Hi Robin,
> > 
> > thanks for looking at this.
> > 
> > On 2026-06-25 at 15:29:10 +0100, Robin Murphy wrote:
> > > On 25/06/2026 2:43 pm, Krzysztof Karas wrote:
> > > > Currently, if iommu maps fewer bytes than requested (iova_len),
> > > > it proceeds to free the iova, but never tries to unmap already
> > > > touched bytes. This behavior may cause memory hogging down the
> > > > line.
> > > 
> > > Huh? iommu_map_sg() has always unmapped internally upon any error - can 
> > > you
> > > clarify how you've seen it returning a short mapping in a non-error case?
> > Yes. I applied some debug logging:
> > 
> > diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> > index 381b60d9e7ce..f166cd31d68f 100644
> > --- a/drivers/iommu/dma-iommu.c
> > +++ b/drivers/iommu/dma-iommu.c
> > @@ -1515,8 +1515,10 @@ int iommu_dma_map_sg(struct device *dev, struct 
> > scatterlist *sg, int nents,
> >           * implementation - it knows better than we do.
> >           */
> >          ret = iommu_map_sg(domain, iova, sg, nents, prot, GFP_ATOMIC);
> > -       if (ret < 0 || ret < iova_len)
> > +       if (ret < 0 || ret < iova_len) {
> > +               printk("%s: ret = %zd, iova_len = %lu\n", __func__, ret, 
> > iova_len);
> >                  goto out_free_iova;
> > +       }
> >          return __finalise_sg(dev, sg, nents, iova);
> > @@ -1525,8 +1527,10 @@ int iommu_dma_map_sg(struct device *dev, struct 
> > scatterlist *sg, int nents,
> >   out_restore_sg:
> >          __invalidate_sg(sg, nents);
> >   out:
> > -       if (ret != -ENOMEM && ret != -EREMOTEIO)
> > +       if (ret != -ENOMEM && ret != -EREMOTEIO) {
> > +               printk("%s: returning -EINVAL\n", __func__);
> >                  return -EINVAL;
> > +       }
> >          return ret;
> >   }
> > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> > index d1a9e713d3a0..59163ad0bce3 100644
> > --- a/drivers/iommu/iommu.c
> > +++ b/drivers/iommu/iommu.c
> > @@ -2900,6 +2900,7 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, 
> > unsigned long iova,
> >          return mapped;
> >   out_err:
> > +       printk("%s: Calling iommu_unmap()\n", __func__);
> >          /* undo mappings already done */
> >          iommu_unmap(domain, iova, mapped);
> > 
> > 
> > and ran "gem_exec_big" with subtest "single" from igt-gpu-tools
> > (./igt-gpu-tools/build/tests/gem_exec_big --run-subtest single)
> > on a Tiger Lake platform. I observed:
> > 
> > [   77.494513] [IGT] gem_exec_big: executing
> > [   77.513162] [IGT] gem_exec_big: starting subtest single
> > [   77.513739] gem_exec_big (2863): drop_caches: 4
> > [   79.912199] i915 0000:00:02.0: Using 39-bit DMA addresses
> > [   79.915571] iommu_dma_map_sg: ret = 7138717696, iova_len = 20023619584   
> > <<===
> 
> OK, yeah, something weird is happening there... Given that you're apparently
> trying to map over 20GB in a single scatterlist, I suspect we might be
> running into some 32-bit integer overflow somewhere - we've certainly hit
> issues with gigantic individual segments in the past - which is then leading
> to the IOVA calculation and/or field-swizzling in iommu_dma_map_sg() itself
> going wrong, or the merging logic in iommu_map_sg(), or perhaps both.
> 
> I'd agree there definitely appears to be a bug here, but ultimately it's
> that iommu_map_sg() is somehow returning a short mapping when it should not,
> so papering over that in iommu-dma is not the solution.
Hmm, so possible overflow and better to dig deeper, got it.
Thanks for your input!

> 
> > [   79.915581] iommu_dma_map_sg: returning -EINVAL
> > [   82.680323] [IGT] gem_exec_big: finished subtest single, SUCCESS
> > [   82.682692] [IGT] gem_exec_big: exiting, ret=0
> > 
> > on a first test execution and then subsequent runs would result
> > DMA remap failures:
> 
> Indeed once the pagetables _have_ got out of sync with the IOVA allocator
> then this is expected behaviour - -EADDRINUSE is generic_pt refusing to map
> over an unexpectedly-present PTE, unlike the old intel-iommu code which
> would have just silently replaced it and succeeded, so if you're only seeing
> these subsequent failures since 6.19, that's probably a factor too.
I do not know when this issue was first introduced, because I
ran into it while debugging other problems addressed in this
series, but since you have a suspicion about 6.19 I'll stick to
that.

-- 
Best Regards,
Krzysztof

Reply via email to