public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
From: Yong Wu <yong.wu@mediatek.com>
To: Will Deacon <will.deacon@arm.com>, Robin Murphy <Robin.Murphy@arm.com>
Cc: Mark Rutland <Mark.Rutland@arm.com>,
	Catalin Marinas <Catalin.Marinas@arm.com>,
	"youhua.li@mediatek.com" <youhua.li@mediatek.com>,
	Thierry Reding <treding@nvidia.com>,
	"k.zhang@mediatek.com" <k.zhang@mediatek.com>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"arnd@arndb.de" <arnd@arndb.de>, Tomasz Figa <tfiga@google.com>,
	Rob Herring <robh+dt@kernel.org>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"pebolle@tiscali.nl" <pebolle@tiscali.nl>,
	"frederic.chen@mediatek.com" <frederic.chen@mediatek.com>,
	"srv_heupstream@mediatek.com" <srv_heupstream@mediatek.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"iommu@lists.linux-foundation.org"
	<iommu@lists.linux-foundation.org>,
	Daniel
Subject: Re: [PATCH v4 3/6] iommu: add ARM short descriptor page table allocator.
Date: Tue, 22 Sep 2015 22:12:47 +0800	[thread overview]
Message-ID: <1442931167.17514.39.camel@mhfsdcap03> (raw)
In-Reply-To: <1442501662.8145.151.camel@mhfsdcap03>

> > > +static int arm_short_unmap(struct io_pgtable_ops *ops,
> > > +                          unsigned long iova,
> > > +                          size_t size)
> > > +{
> > > +       struct arm_short_io_pgtable *data = io_pgtable_ops_to_data(ops);
> > > +       struct io_pgtable_cfg *cfg = &data->iop.cfg;
> > > +       arm_short_iopte *pgd, *pte = NULL;
> > > +       arm_short_iopte curpgd, curpte = 0;
> > > +       phys_addr_t paddr;
> > > +       unsigned int iova_base, blk_size = 0;
> > > +       void *cookie = data->iop.cookie;
> > > +       bool pgtablefree = false;
> > > +
> > > +       pgd = (arm_short_iopte *)data->pgd + ARM_SHORT_PGD_IDX(iova);
> > > +
> > > +       /* Get block size */
> > > +       if (ARM_SHORT_PGD_TYPE_IS_PGTABLE(*pgd)) {
> > > +               pte = arm_short_get_pte_in_pgd(*pgd, iova);
> > > +
> > > +               if (ARM_SHORT_PTE_TYPE_IS_SMALLPAGE(*pte))
> > > +                       blk_size = SZ_4K;
> > > +               else if (ARM_SHORT_PTE_TYPE_IS_LARGEPAGE(*pte))
> > > +                       blk_size = SZ_64K;
> > > +               else
> > > +                       WARN_ON(1);
> 
> > > +       } else if (ARM_SHORT_PGD_TYPE_IS_SECTION(*pgd)) {
> > > +               blk_size = SZ_1M;
> > > +       } else if (ARM_SHORT_PGD_TYPE_IS_SUPERSECTION(*pgd)) {
> > > +               blk_size = SZ_16M;
> > > +       } else {
> > > +               WARN_ON(1); 
> > > +       }
> > > +
> > > +       iova_base = iova & ~(blk_size - 1);
> > > +       pgd = (arm_short_iopte *)data->pgd + ARM_SHORT_PGD_IDX(iova_base);
> > > +       paddr = arm_short_iova_to_phys(ops, iova_base);
> > > +       curpgd = *pgd;
> > > +
> > > +       if (blk_size == SZ_4K || blk_size == SZ_64K) {
> > > +               pte = arm_short_get_pte_in_pgd(*pgd, iova_base);
> > > +               curpte = *pte;
> > > +               __arm_short_set_pte(pte, 0, blk_size / SZ_4K, cfg);
> > > +
> > > +            pgtablefree = _arm_short_whether_free_pgtable(pgd);
> > > +            if (pgtablefree)
> > > +                 __arm_short_set_pte(pgd, 0, 1, cfg);
> > > +       } else if (blk_size == SZ_1M || blk_size == SZ_16M) {
> > > +               __arm_short_set_pte(pgd, 0, blk_size / SZ_1M, cfg);
> > > +       }
> > > +
> > > +    cfg->tlb->tlb_add_flush(iova_base, blk_size, true, cookie);
> > > +    cfg->tlb->tlb_sync(cookie);
> > > +
> > > +       if (pgtablefree)/* Free pgtable after tlb-flush */
> > > +              __arm_short_free_pgtable(ARM_SHORT_GET_PGTABLE_VA(curpgd),
> > > +                                        ARM_SHORT_BYTES_PER_PTE, false, cfg);
> > > +
> > > +       if (blk_size > size) { /* Split the block */
> > > +               return arm_short_split_blk_unmap(
> > > +                               ops, iova, paddr, size,
> > > +                               ARM_SHORT_PGD_GET_PROT(curpgd),
> > > +                               ARM_SHORT_PTE_LARGE_GET_PROT(curpte),
> > > +                               blk_size);
> > > +       } else if (blk_size < size) {
> > > +               /* Unmap the block while remap partial again after split */
> > > +               return blk_size +
> > > +                       arm_short_unmap(ops, iova + blk_size, size - blk_size);

Hi Will, Robin,
     I would like to show you a problem I met, The recursion here may
lead to stack overflow while we test FHD video decode.

    From the log, I get the internal variable in the error case: the
"size" is 0x100000, the "iova" is 0xfea00000, but at that time the
"blk_size" is 0x1000 as it was the map of small-page. so it enter the
recursion here.
    
    After check the unmap flow, there is only a iommu_unmap in
__iommu_dma_unmap, and it won't check the physical address align in
iommu_unmap.
so if the iova and size both are SZ_16M or SZ_1M align by chance, it
also enter the arm_short_unmap even though it was the map of small-page.

    So.
    a) Do we need unmap each sg item while iommu_dma_unmap?, like below:

//===============
static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t
dma_addr)
{
	/* ...and if we can't, then something is horribly, horribly wrong */
+       for_each_sg(sg, s, nents, i)
		BUG_ON(iommu_unmap(domain, pfn << shift, size) < size);
	__free_iova(iovad, iova);
}
//===============
 
    b). I need to add do-while which was suggested to delete from [1] in
arm_short_unmap for this case.

     After I test locally, I prepare to add the do-while like below:
     
//==============================
static int arm_short_unmap(struct io_pgtable_ops *ops,
			   unsigned long iova,
			   size_t size)
{
	struct arm_short_io_pgtable *data = io_pgtable_ops_to_data(ops);
	struct io_pgtable_cfg *cfg = &data->iop.cfg;
	arm_short_iopte *pgd, *pte = NULL;
	arm_short_iopte curpgd, curpte = 0;
	unsigned int blk_base, blk_size;
	int unmap_size = 0;
	bool pgtempty;

	do {
		pgd = (arm_short_iopte *)data->pgd + ARM_SHORT_PGD_IDX(iova);
		blk_size = 0;
		pgtempty = false;

		/* Get block size */
		if (ARM_SHORT_PGD_TYPE_IS_PGTABLE(*pgd)) {
			pte = arm_short_get_pte_in_pgd(*pgd, iova);

			if (ARM_SHORT_PTE_TYPE_IS_SMALLPAGE(*pte))
				blk_size = SZ_4K;
			else if (ARM_SHORT_PTE_TYPE_IS_LARGEPAGE(*pte))
				blk_size = SZ_64K;
		} else if (ARM_SHORT_PGD_TYPE_IS_SECTION(*pgd)) {
			blk_size = SZ_1M;
		} else if (ARM_SHORT_PGD_TYPE_IS_SUPERSECTION(*pgd)) {
			blk_size = SZ_16M;
		}

		if (WARN_ON(!blk_size))
			return 0;

		blk_base = iova & ~(blk_size - 1);
		pgd = (arm_short_iopte *)data->pgd + ARM_SHORT_PGD_IDX(blk_base);
		curpgd = *pgd;

		if (blk_size == SZ_4K || blk_size == SZ_64K) {
			pte = arm_short_get_pte_in_pgd(*pgd, blk_base);
			curpte = *pte;
			__arm_short_set_pte(pte, 0, blk_size / SZ_4K, cfg);

			pgtempty = __arm_short_pgtable_empty(pgd);
			if (pgtempty)
				__arm_short_set_pte(pgd, 0, 1, cfg);
		} else if (blk_size == SZ_1M || blk_size == SZ_16M) {
			__arm_short_set_pte(pgd, 0, blk_size / SZ_1M, cfg);
		}

		cfg->tlb->tlb_add_flush(blk_base, blk_size, true, data->iop.cookie);
		cfg->tlb->tlb_sync(data->iop.cookie);

		if (pgtempty)/* Free lvl2 pgtable after tlb-flush */
			__arm_short_free_pgtable(
					ARM_SHORT_GET_PGTABLE_VA(curpgd),
					ARM_SHORT_BYTES_PER_PTE, false, cfg);

		/*
		 * If the unmap size which is from the pgsize_bitmap is more
		 * than the current blk_size, unmap it continuously.
		 */
		if (blk_size <= size) {
			iova += blk_size;
			size -= blk_size;
			unmap_size += blk_size;
			continue;
		} else { /* Split this block */
			return arm_short_split_blk_unmap(
					ops, iova, size, blk_size,
					ARM_SHORT_PGD_GET_PROT(curpgd),
					ARM_SHORT_PTE_GET_PROT_LARGE(curpte));
		}
	}while (size);

	return unmap_size;
}
//=============================

    Is there any other suggestion?
    Thanks very much.


[1]:http://lists.linuxfoundation.org/pipermail/iommu/2015-June/013322.html

> > > +       }
> > > +
> > > +       return size;
> > > +}
> > > +
> _______________________________________________
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu

  reply	other threads:[~2015-09-22 14:12 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-03 10:21 [PATCH v4 0/6] MT8173 IOMMU SUPPORT Yong Wu
     [not found] ` <1438597279-2937-1-git-send-email-yong.wu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-08-03 10:21   ` [PATCH v4 1/6] dt-bindings: iommu: Add binding for mediatek IOMMU Yong Wu
2015-08-03 10:21   ` [PATCH v4 2/6] dt-bindings: mediatek: Add smi dts binding Yong Wu
2015-08-03 10:21   ` [PATCH v4 3/6] iommu: add ARM short descriptor page table allocator Yong Wu
     [not found]     ` <1438597279-2937-4-git-send-email-yong.wu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-09-16 15:58       ` Will Deacon
     [not found]         ` <20150916155824.GM28771-5wv7dgnIgG8@public.gmane.org>
2015-09-17 14:54           ` Yong Wu
2015-09-22 14:12             ` Yong Wu [this message]
2015-10-09 15:57               ` Will Deacon
     [not found]                 ` <20151009155750.GS26278-5wv7dgnIgG8@public.gmane.org>
2015-10-09 17:41                   ` Robin Murphy
     [not found]                     ` <5617FC5F.60505-5wv7dgnIgG8@public.gmane.org>
2015-10-09 18:19                       ` Will Deacon
     [not found]                         ` <20151009181929.GU26278-5wv7dgnIgG8@public.gmane.org>
2015-10-21 10:34                           ` Yong Wu
2015-08-03 10:21   ` [PATCH v4 4/6] memory: mediatek: Add SMI driver Yong Wu
     [not found]     ` <1438597279-2937-5-git-send-email-yong.wu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-08-11 14:56       ` Joerg Roedel
2015-08-12 12:39         ` Yong Wu
2015-08-03 10:21   ` [PATCH v4 5/6] iommu/mediatek: Add mt8173 IOMMU driver Yong Wu
     [not found]     ` <1438597279-2937-6-git-send-email-yong.wu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-08-11 15:39       ` Joerg Roedel
     [not found]         ` <20150811153947.GF14980-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-08-12 12:28           ` Yong Wu
2015-09-11 15:33       ` Robin Murphy
     [not found]         ` <55F2F450.5090809-5wv7dgnIgG8@public.gmane.org>
2015-09-15  5:53           ` Yong Wu
2015-08-03 10:21   ` [PATCH v4 6/6] dts: mt8173: Add iommu/smi nodes for mt8173 Yong Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1442931167.17514.39.camel@mhfsdcap03 \
    --to=yong.wu@mediatek.com \
    --cc=Catalin.Marinas@arm.com \
    --cc=Mark.Rutland@arm.com \
    --cc=Robin.Murphy@arm.com \
    --cc=arnd@arndb.de \
    --cc=devicetree@vger.kernel.org \
    --cc=frederic.chen@mediatek.com \
    --cc=iommu@lists.linux-foundation.org \
    --cc=k.zhang@mediatek.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=matthias.bgg@gmail.com \
    --cc=pebolle@tiscali.nl \
    --cc=robh+dt@kernel.org \
    --cc=srv_heupstream@mediatek.com \
    --cc=tfiga@google.com \
    --cc=treding@nvidia.com \
    --cc=will.deacon@arm.com \
    --cc=youhua.li@mediatek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox