Hi Oleksandr, Thank you for the patch.
On Wednesday, 23 August 2017 17:31:42 EEST Oleksandr Tyshchenko wrote: > From: Oleksandr Tyshchenko <oleksandr_tyshche...@epam.com> > > Reserving a free context is both quicker and more likely to fail > (due to limited hardware resources) than setting up a pagetable. > What is more the pagetable init/cleanup code could require > the context to be set up. > > Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshche...@epam.com> > CC: Robin Murphy <robin.mur...@arm.com> > CC: Laurent Pinchart <laurent.pinch...@ideasonboard.com> > CC: Joerg Roedel <j...@8bytes.org> Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com> > --- > This patch fixes a bug during rollback logic: > In ipmmu_domain_init_context() we are trying to find an unused context > and if operation fails we will call free_io_pgtable_ops(), > but "domain->context_id" hasn't been initialized yet (likely it is 0 > because of kzalloc). Having the following call stack: > free_io_pgtable_ops() -> io_pgtable_tlb_flush_all() -> > ipmmu_tlb_flush_all() -> ipmmu_tlb_invalidate() > we will get a mistaken cache flush for a context pointed by > uninitialized "domain->context_id". > > > v1 here: > https://lists.linuxfoundation.org/pipermail/iommu/2017-August/023857.html > --- > drivers/iommu/ipmmu-vmsa.c | 42 +++++++++++++++++++++--------------------- > 1 file changed, 21 insertions(+), 21 deletions(-) > > diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c > index 2a38aa1..382f387 100644 > --- a/drivers/iommu/ipmmu-vmsa.c > +++ b/drivers/iommu/ipmmu-vmsa.c > @@ -341,6 +341,19 @@ static int ipmmu_domain_allocate_context(struct > ipmmu_vmsa_device *mmu, return ret; > } > > +static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu, > + unsigned int context_id) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&mmu->lock, flags); > + > + clear_bit(context_id, mmu->ctx); > + mmu->domains[context_id] = NULL; > + > + spin_unlock_irqrestore(&mmu->lock, flags); > +} > + > static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain) > { > u64 ttbr; > @@ -370,22 +383,22 @@ static int ipmmu_domain_init_context(struct > ipmmu_vmsa_domain *domain) */ > domain->cfg.iommu_dev = domain->mmu->dev; > > - domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg, > - domain); > - if (!domain->iop) > - return -EINVAL; > - > /* > * Find an unused context. > */ > ret = ipmmu_domain_allocate_context(domain->mmu, domain); > - if (ret == IPMMU_CTX_MAX) { > - free_io_pgtable_ops(domain->iop); > + if (ret == IPMMU_CTX_MAX) > return -EBUSY; > - } > > domain->context_id = ret; > > + domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg, > + domain); > + if (!domain->iop) { > + ipmmu_domain_free_context(domain->mmu, domain->context_id); > + return -EINVAL; > + } > + > /* TTBR0 */ > ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0]; > ipmmu_ctx_write(domain, IMTTLBR0, ttbr); > @@ -426,19 +439,6 @@ static int ipmmu_domain_init_context(struct > ipmmu_vmsa_domain *domain) return 0; > } > > -static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu, > - unsigned int context_id) > -{ > - unsigned long flags; > - > - spin_lock_irqsave(&mmu->lock, flags); > - > - clear_bit(context_id, mmu->ctx); > - mmu->domains[context_id] = NULL; > - > - spin_unlock_irqrestore(&mmu->lock, flags); > -} > - > static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain) > { > /* -- Regards, Laurent Pinchart _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu