[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <691bd1d4-ba5f-dd82-2866-d64cd2d6b55e@arm.com>
Date: Tue, 26 Sep 2017 19:15:47 +0100
From: Robin Murphy <robin.murphy@....com>
To: "Raj, Ashok" <ashok.raj@...el.com>
Cc: Harsh Jain <Harsh@...lsio.com>, Casey Leedom <leedom@...lsio.com>,
Herbert Xuy <herbert@...dor.apana.org.au>,
David Woodhouse <David.Woodhouse@...el.com>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"iommu@...ts.linux-foundation.org" <iommu@...ts.linux-foundation.org>,
"linux-crypto@...r.kernel.org" <linux-crypto@...r.kernel.org>,
Dan Williams <dan.j.williams@...el.com>,
"dwmw2@...radead.org" <dwmw2@...radead.org>
Subject: Re: DMA error when sg->offset value is greater than PAGE_SIZE in
Intel IOMMU
On 26/09/17 15:34, Raj, Ashok wrote:
> 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?
PAGE_MASK (and the corresponding pteval arithmetic) was intentional
here; given the way aligned_nrpages() works, the IOVA space allocated in
intel_map_sg() (and thus iov_pfn) is already rounded to full MM pages,
and it seemed like the original intent was to map the whole lot - this
change is just to make that happen correctly.
Whether it's actually reasonable to decouple the IOMMU and CPU page
sizes entirely (as we do in dma-iommu, for example), and not do the
MM-page-alignment thing at all, is another matter that I'm happy to
leave in your hands :)
Robin.
>> +
>> 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
>
Powered by blists - more mailing lists