On Tue, Sep 26, 2017 at 03:22:47PM +0100, Robin Murphy wrote: > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index 6784a05dd6b2..d7f7def81613 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -2254,10 +2254,12 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, > uint64_t tmp; > > if (!sg_res) { > + size_t off = sg->offset & ~PAGE_MASK; Should this be VTD_PAGE_MASK? > + > sg_res = aligned_nrpages(sg->offset, sg->length); > - sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; > + sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + off; > sg->dma_length = sg->length; > - pteval = page_to_phys(sg_page(sg)) | prot; > + pteval = (page_to_phys(sg_page(sg)) + sg->offset - off) | prot; Something seems wrong here.. sg->offset can be > VTD_PAGE_SIZE, think we should add sg->offset and then find the pteval? attached below another cut at fixing the same problem.. if there is something obvious i missed, let me know. again.. untested :-) Cheers, Ashok
Sometimes offset can be greater than 4K. vt-d needs to account for that. From: Ashok Raj <ashok.raj@xxxxxxxxx> Signed-off-by: Ashok Raj <ashok.raj@xxxxxxxxx> --- drivers/iommu/intel-iommu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 6784a05..d43b566 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2254,10 +2254,13 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, uint64_t tmp; if (!sg_res) { + size_t off = sg->offset & ~VTD_PAGE_SHIFT; sg_res = aligned_nrpages(sg->offset, sg->length); - sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; + sg->dma_address = ((dma_addr_t) + (iov_pfn + sg->offset) << VTD_PAGE_SHIFT) + off; sg->dma_length = sg->length; - pteval = page_to_phys(sg_page(sg)) | prot; + pteval = (page_to_phys(sg_page(sg)) + + (sg->offset << VTD_PAGE_SHIFT)) | prot; phys_pfn = pteval >> VTD_PAGE_SHIFT; }