From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B6BC5C4345F for ; Tue, 30 Apr 2024 15:05:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:From:References:Cc:To: Subject:MIME-Version:Date:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=QwyAv0vJAEW/oFaKhJ6HYVan/nwja58lEFL1Lh+1PIA=; b=fK4IbgJ/8EMpU9 DTEd535B7TRUjnhmLA246jlksZVPyPSK5oaS7SB8HXfL3A/gSO7OQKb/Of5RK9fYjMGdBl3tIKXlD qYywLm4rev7jRckYyVUp/lAGP8/Apsiv3YvoT2avLBcEFbF0XhPc812tHhhRC9fm5OJAf8/5596kr RqeFvnrXXzz7DLj1dPR9GbPBjNilL591QLV28TQLQZa20f0VmKGYHvcNtnDSsjA34E8aI+wFQbD3x QVolcvhZnBtawxqOU278PvKzmDnz3JWrsPPgDIReKlnpyzxIAHgtglhgLiTqJfJtrMOk6l1cKUEPV iHF+ryedk/QSJBYy+gQA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1s1p2y-00000006yd6-3PbS; Tue, 30 Apr 2024 15:05:32 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1s1p2u-00000006ybc-3As7 for linux-arm-kernel@lists.infradead.org; Tue, 30 Apr 2024 15:05:30 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3F9AE2F4; Tue, 30 Apr 2024 08:05:53 -0700 (PDT) Received: from [10.1.38.140] (XHFQ2J9959.cambridge.arm.com [10.1.38.140]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 06C1E3F793; Tue, 30 Apr 2024 08:05:24 -0700 (PDT) Message-ID: <9ef76f06-9538-473c-9785-520350b1cee6@arm.com> Date: Tue, 30 Apr 2024 16:05:23 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v3 3/4] iommu/arm-smmu-v3: Add support for dirty tracking in domain alloc Content-Language: en-GB To: Shameer Kolothum , iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: robin.murphy@arm.com, will@kernel.org, joro@8bytes.org, jgg@nvidia.com, kevin.tian@intel.com, nicolinc@nvidia.com, mshavit@google.com, eric.auger@redhat.com, joao.m.martins@oracle.com, jiangkunkun@huawei.com, zhukeqian1@huawei.com, linuxarm@huawei.com References: <20240430134308.1604-1-shameerali.kolothum.thodi@huawei.com> <20240430134308.1604-4-shameerali.kolothum.thodi@huawei.com> From: Ryan Roberts In-Reply-To: <20240430134308.1604-4-shameerali.kolothum.thodi@huawei.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240430_080528_925361_807972F1 X-CRM114-Status: GOOD ( 27.40 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org On 30/04/2024 14:43, Shameer Kolothum wrote: > From: Joao Martins > > This provides all the infrastructure to enable dirty tracking if the > hardware has the capability and domain alloc request for it. > > Please note, we still report no support for IOMMU_CAP_DIRTY_TRACKING > as it will finally be enabled in a subsequent patch. > > Signed-off-by: Joao Martins > Signed-off-by: Shameer Kolothum Reviewed-by: Ryan Roberts > --- > drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 82 +++++++++++++++------ > include/linux/io-pgtable.h | 4 + > 2 files changed, 63 insertions(+), 23 deletions(-) > > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > index bed0183ba809..ad18436c5f7f 100644 > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c > @@ -38,6 +38,7 @@ MODULE_PARM_DESC(disable_msipolling, > "Disable MSI-based polling for CMD_SYNC completion."); > > static struct iommu_ops arm_smmu_ops; > +static struct iommu_dirty_ops arm_smmu_dirty_ops; > > enum arm_smmu_msi_index { > EVTQ_MSI_INDEX, > @@ -80,7 +81,8 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { > }; > > static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain, > - struct arm_smmu_device *smmu); > + struct arm_smmu_device *smmu, > + u32 flags); > static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master); > static void arm_smmu_tlb_inv_all_s2(struct arm_smmu_domain *smmu_domain); > > @@ -2335,7 +2337,7 @@ static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev) > struct arm_smmu_master *master = dev_iommu_priv_get(dev); > int ret; > > - ret = arm_smmu_domain_finalise(smmu_domain, master->smmu); > + ret = arm_smmu_domain_finalise(smmu_domain, master->smmu, 0); > if (ret) { > kfree(smmu_domain); > return ERR_PTR(ret); > @@ -2408,13 +2410,14 @@ static void arm_smmu_domain_free_paging(struct iommu_domain *domain) > } > > static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain, > - struct arm_smmu_device *smmu) > + struct arm_smmu_device *smmu, > + u32 flags) > { > int ret; > - unsigned long ias, oas; > enum io_pgtable_fmt fmt; > struct io_pgtable_cfg pgtbl_cfg; > struct io_pgtable_ops *pgtbl_ops; > + bool enable_dirty = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING; > > /* Restrict the stage to what we can actually support */ > if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1)) > @@ -2422,31 +2425,32 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain, > if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2)) > smmu_domain->stage = ARM_SMMU_DOMAIN_S1; > > + pgtbl_cfg = (struct io_pgtable_cfg) { > + .pgsize_bitmap = smmu->pgsize_bitmap, > + .coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENCY, > + .tlb = &arm_smmu_flush_ops, > + .iommu_dev = smmu->dev, > + }; > + > switch (smmu_domain->stage) { > case ARM_SMMU_DOMAIN_S1: > - ias = (smmu->features & ARM_SMMU_FEAT_VAX) ? 52 : 48; > - ias = min_t(unsigned long, ias, VA_BITS); > - oas = smmu->ias; > + unsigned long ias = (smmu->features & > + ARM_SMMU_FEAT_VAX) ? 52 : 48; > + pgtbl_cfg.ias = min_t(unsigned long, ias, VA_BITS); > + pgtbl_cfg.oas = smmu->ias; > + if (enable_dirty) > + pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_ARM_HD; > fmt = ARM_64_LPAE_S1; > break; > case ARM_SMMU_DOMAIN_S2: > - ias = smmu->ias; > - oas = smmu->oas; > + pgtbl_cfg.ias = smmu->ias; > + pgtbl_cfg.oas = smmu->oas; > fmt = ARM_64_LPAE_S2; > break; > default: > return -EINVAL; > } > > - pgtbl_cfg = (struct io_pgtable_cfg) { > - .pgsize_bitmap = smmu->pgsize_bitmap, > - .ias = ias, > - .oas = oas, > - .coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENCY, > - .tlb = &arm_smmu_flush_ops, > - .iommu_dev = smmu->dev, > - }; > - > pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain); > if (!pgtbl_ops) > return -ENOMEM; > @@ -2454,7 +2458,8 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain, > smmu_domain->domain.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; > smmu_domain->domain.geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1; > smmu_domain->domain.geometry.force_aperture = true; > - > + if (enable_dirty && smmu_domain->stage == ARM_SMMU_DOMAIN_S1) > + smmu_domain->domain.dirty_ops = &arm_smmu_dirty_ops; > ret = arm_smmu_domain_alloc_id(smmu, smmu_domain); > if (ret < 0) { > free_io_pgtable_ops(pgtbl_ops); > @@ -2777,7 +2782,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) > mutex_lock(&smmu_domain->init_mutex); > > if (!smmu_domain->smmu) { > - ret = arm_smmu_domain_finalise(smmu_domain, smmu); > + ret = arm_smmu_domain_finalise(smmu_domain, smmu, 0); > } else if (smmu_domain->smmu != smmu) > ret = -EINVAL; > > @@ -2842,7 +2847,7 @@ static int arm_smmu_s1_set_dev_pasid(struct iommu_domain *domain, > > mutex_lock(&smmu_domain->init_mutex); > if (!smmu_domain->smmu) > - ret = arm_smmu_domain_finalise(smmu_domain, smmu); > + ret = arm_smmu_domain_finalise(smmu_domain, smmu, 0); > else if (smmu_domain->smmu != smmu) > ret = -EINVAL; > mutex_unlock(&smmu_domain->init_mutex); > @@ -3175,7 +3180,8 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, > const struct iommu_user_data *user_data) > { > struct arm_smmu_master *master = dev_iommu_priv_get(dev); > - const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_NEST_PARENT; > + const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_NEST_PARENT | > + IOMMU_HWPT_ALLOC_DIRTY_TRACKING; > struct arm_smmu_domain *smmu_domain; > int ret; > > @@ -3188,6 +3194,10 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, > if (user_data) > return ERR_PTR(-EINVAL); > > + if ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) && > + !device_iommu_capable(dev, IOMMU_CAP_DIRTY_TRACKING)) > + return ERR_PTR(-EOPNOTSUPP); > + > smmu_domain = arm_smmu_domain_alloc(); > if (!smmu_domain) > return ERR_PTR(-ENOMEM); > @@ -3203,7 +3213,7 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags, > > smmu_domain->domain.type = IOMMU_DOMAIN_UNMANAGED; > smmu_domain->domain.ops = arm_smmu_ops.default_domain_ops; > - ret = arm_smmu_domain_finalise(smmu_domain, master->smmu); > + ret = arm_smmu_domain_finalise(smmu_domain, master->smmu, flags); > if (ret) > goto err_free; > return &smmu_domain->domain; > @@ -3479,6 +3489,27 @@ static void arm_smmu_release_device(struct device *dev) > kfree(master); > } > > +static int arm_smmu_read_and_clear_dirty(struct iommu_domain *domain, > + unsigned long iova, size_t size, > + unsigned long flags, > + struct iommu_dirty_bitmap *dirty) > +{ > + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); > + struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops; > + > + return ops->read_and_clear_dirty(ops, iova, size, flags, dirty); > +} > + > +static int arm_smmu_set_dirty_tracking(struct iommu_domain *domain, > + bool enabled) > +{ > + /* > + * Always enabled and the dirty bitmap is cleared prior to > + * set_dirty_tracking(). > + */ > + return 0; > +} > + > static struct iommu_group *arm_smmu_device_group(struct device *dev) > { > struct iommu_group *group; > @@ -3622,6 +3653,11 @@ static struct iommu_ops arm_smmu_ops = { > } > }; > > +static struct iommu_dirty_ops arm_smmu_dirty_ops = { > + .read_and_clear_dirty = arm_smmu_read_and_clear_dirty, > + .set_dirty_tracking = arm_smmu_set_dirty_tracking, > +}; > + > /* Probing and initialisation functions */ > static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, > struct arm_smmu_queue *q, > diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h > index 86cf1f7ae389..8e75f944f07a 100644 > --- a/include/linux/io-pgtable.h > +++ b/include/linux/io-pgtable.h > @@ -85,6 +85,8 @@ struct io_pgtable_cfg { > * > * IO_PGTABLE_QUIRK_ARM_OUTER_WBWA: Override the outer-cacheability > * attributes set in the TCR for a non-coherent page-table walker. > + * > + * IO_PGTABLE_QUIRK_ARM_HD: Enables dirty tracking in stage 1 pagetable. > */ > #define IO_PGTABLE_QUIRK_ARM_NS BIT(0) > #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) > @@ -92,6 +94,8 @@ struct io_pgtable_cfg { > #define IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT BIT(4) > #define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5) > #define IO_PGTABLE_QUIRK_ARM_OUTER_WBWA BIT(6) > + #define IO_PGTABLE_QUIRK_ARM_HD BIT(7) > + > unsigned long quirks; > unsigned long pgsize_bitmap; > unsigned int ias; _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel