* [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3
@ 2024-05-28 7:18 Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 1/7] iommu/arm-smmu-v3: Convert to domain_alloc_sva() Shameer Kolothum
` (6 more replies)
0 siblings, 7 replies; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
Hi,
v3 --> v4
-Re-based on top of 6.10-rc1
-Added patches (1, 2 & 3) on top of v3 to make this series independent
of Jason's SMMUv3 refactor series.
-Addressed comments received on v3 and added tags.
Please take a look and let me know your feedback.
Thanks,
Shameer
---
This is revisiting the earlier attempts [1, 2] to use SMMUv3 HTTU feature
for dirty page tracking. The Intel/AMD support is already mainline.
Basic sanity tests are done using an emulation setup and on a test
hardware setup. Block page split/merge(BBML) is not part of this
series. I am planning to send it separately.
v2 --> v3
-Rebased on top of the latest of Jason's refactor series git[3].
-Addressed comments from Ryan and Jason(patch 2 & 3, Thanks!)
-Added R-by tags to 1 & 4.
v1 --> v2:
https://lore.kernel.org/linux-iommu/20231128094940.1344-1-shameerali.kolothum.thodi@huawei.com/
Addressed review comments from Jason and Joao(Thanks)
-Moved dirty_ops setting to domain finalise(patch #3)
-Only enable DBM for stage 1 if domain_alloc_user() requests it.
-Changed IO page table walker(patch #2) and tested with 4KB/16KB/64KB
with l1/l2/l3 traversal.(The earlier one had a bug where it fails to
walk L3 level).
-Rearranged patches a bit to improve bi-sectability.
-Rebased on top of Jason's v5 of SMMUv3 new API series git.
1. https://lore.kernel.org/lkml/20210413085457.25400-1-zhukeqian1@huawei.com/
2. https://lore.kernel.org/linux-iommu/20230518204650.14541-1-joao.m.martins@oracle.com/
3. https://github.com/jgunthorpe/linux/commits/smmuv3_newapi
Jason Gunthorpe (2):
iommu/arm-smmu-v3: Convert to domain_alloc_sva()
iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc()
Jean-Philippe Brucker (1):
iommu/arm-smmu-v3: Add feature detection for HTTU
Joao Martins (1):
iommu/arm-smmu-v3: Add support for dirty tracking in domain alloc
Kunkun Jiang (1):
iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping
Shameer Kolothum (2):
iommu/arm-smmu-v3: Add support for domain_alloc_user fn
iommu/io-pgtable-arm: Add read_and_clear_dirty() support
drivers/iommu/Kconfig | 1 +
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 21 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 192 ++++++++++++++----
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 16 +-
drivers/iommu/io-pgtable-arm.c | 119 ++++++++++-
drivers/iommu/iommufd/hw_pagetable.c | 3 +
include/linux/io-pgtable.h | 4 +
7 files changed, 307 insertions(+), 49 deletions(-)
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v4 1/7] iommu/arm-smmu-v3: Convert to domain_alloc_sva()
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc() Shameer Kolothum
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
From: Jason Gunthorpe <jgg@nvidia.com>
This allows the driver the receive the mm and a always a device during
allocation. Later patches need this to properly setup the notifier when
the domain is first allocated.
Remove ops->domain_alloc() as SVA was the only remaining purpose.
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Michael Shavit <mshavit@google.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 6 ++++--
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 10 +---------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 6 +++++-
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index e490ffb38015..28f8bf4327f6 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -656,13 +656,15 @@ static const struct iommu_domain_ops arm_smmu_sva_domain_ops = {
.free = arm_smmu_sva_domain_free
};
-struct iommu_domain *arm_smmu_sva_domain_alloc(void)
+struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
+ struct mm_struct *mm)
{
struct iommu_domain *domain;
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
- return NULL;
+ return ERR_PTR(-ENOMEM);
+ domain->type = IOMMU_DOMAIN_SVA;
domain->ops = &arm_smmu_sva_domain_ops;
return domain;
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 ab415e107054..bd79422f7b6f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2237,14 +2237,6 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
}
}
-static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
-{
-
- if (type == IOMMU_DOMAIN_SVA)
- return arm_smmu_sva_domain_alloc();
- return ERR_PTR(-EOPNOTSUPP);
-}
-
static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
{
struct arm_smmu_domain *smmu_domain;
@@ -3097,8 +3089,8 @@ static struct iommu_ops arm_smmu_ops = {
.identity_domain = &arm_smmu_identity_domain,
.blocked_domain = &arm_smmu_blocked_domain,
.capable = arm_smmu_capable,
- .domain_alloc = arm_smmu_domain_alloc,
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
+ .domain_alloc_sva = arm_smmu_sva_domain_alloc,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
.device_group = arm_smmu_device_group,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 1242a086c9f9..4c6c843669aa 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -802,7 +802,8 @@ int arm_smmu_master_enable_sva(struct arm_smmu_master *master);
int arm_smmu_master_disable_sva(struct arm_smmu_master *master);
bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master);
void arm_smmu_sva_notifier_synchronize(void);
-struct iommu_domain *arm_smmu_sva_domain_alloc(void);
+struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
+ struct mm_struct *mm);
void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
struct device *dev, ioasid_t id);
#else /* CONFIG_ARM_SMMU_V3_SVA */
@@ -848,5 +849,8 @@ static inline void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
ioasid_t id)
{
}
+
+#define arm_smmu_sva_domain_alloc NULL
+
#endif /* CONFIG_ARM_SMMU_V3_SVA */
#endif /* _ARM_SMMU_V3_H */
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc()
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 1/7] iommu/arm-smmu-v3: Convert to domain_alloc_sva() Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
2024-06-01 21:06 ` Jason Gunthorpe
2024-05-28 7:18 ` [PATCH v4 3/7] iommu/arm-smmu-v3: Add support for domain_alloc_user fn Shameer Kolothum
` (4 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
From: Jason Gunthorpe <jgg@nvidia.com>
And use that for arm_smmu_domain_alloc_paging() and
arm_smmu_sva_domain_alloc()
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 19 +++++++------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 27 +++++++++++++------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 ++
3 files changed, 32 insertions(+), 16 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 28f8bf4327f6..70c95887757f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -648,7 +648,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
static void arm_smmu_sva_domain_free(struct iommu_domain *domain)
{
- kfree(domain);
+ kfree(to_smmu_domain(domain));
}
static const struct iommu_domain_ops arm_smmu_sva_domain_ops = {
@@ -659,13 +659,16 @@ static const struct iommu_domain_ops arm_smmu_sva_domain_ops = {
struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
struct mm_struct *mm)
{
- struct iommu_domain *domain;
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ struct arm_smmu_device *smmu = master->smmu;
+ struct arm_smmu_domain *smmu_domain;
- domain = kzalloc(sizeof(*domain), GFP_KERNEL);
- if (!domain)
- return ERR_PTR(-ENOMEM);
- domain->type = IOMMU_DOMAIN_SVA;
- domain->ops = &arm_smmu_sva_domain_ops;
+ smmu_domain = arm_smmu_domain_alloc();
+ if (IS_ERR(smmu_domain))
+ return ERR_CAST(smmu_domain);
+ smmu_domain->domain.type = IOMMU_DOMAIN_SVA;
+ smmu_domain->domain.ops = &arm_smmu_sva_domain_ops;
+ smmu_domain->smmu = smmu;
- return domain;
+ return &smmu_domain->domain;
}
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 bd79422f7b6f..b574a36a7b95 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2237,15 +2237,10 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
}
}
-static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
+struct arm_smmu_domain *arm_smmu_domain_alloc(void)
{
struct arm_smmu_domain *smmu_domain;
- /*
- * Allocate the domain and initialise some of its data structures.
- * We can't really do anything meaningful until we've added a
- * master.
- */
smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL);
if (!smmu_domain)
return ERR_PTR(-ENOMEM);
@@ -2255,6 +2250,22 @@ static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
spin_lock_init(&smmu_domain->devices_lock);
INIT_LIST_HEAD(&smmu_domain->mmu_notifiers);
+ return smmu_domain;
+}
+
+static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
+{
+ struct arm_smmu_domain *smmu_domain;
+
+ /*
+ * Allocate the domain and initialise some of its data structures.
+ * We can't really do anything meaningful until we've added a
+ * master.
+ */
+ smmu_domain = arm_smmu_domain_alloc();
+ if (IS_ERR(smmu_domain))
+ return ERR_CAST(smmu_domain);
+
if (dev) {
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
int ret;
@@ -2268,7 +2279,7 @@ static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
return &smmu_domain->domain;
}
-static void arm_smmu_domain_free(struct iommu_domain *domain)
+static void arm_smmu_domain_free_paging(struct iommu_domain *domain)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
@@ -3111,7 +3122,7 @@ static struct iommu_ops arm_smmu_ops = {
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
.enable_nesting = arm_smmu_enable_nesting,
- .free = arm_smmu_domain_free,
+ .free = arm_smmu_domain_free_paging,
}
};
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 4c6c843669aa..e67ce0f8867f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -774,6 +774,8 @@ static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
extern struct xarray arm_smmu_asid_xa;
extern struct mutex arm_smmu_asid_lock;
+struct arm_smmu_domain *arm_smmu_domain_alloc(void);
+
void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid);
struct arm_smmu_cd *arm_smmu_get_cd_ptr(struct arm_smmu_master *master,
u32 ssid);
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 3/7] iommu/arm-smmu-v3: Add support for domain_alloc_user fn
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 1/7] iommu/arm-smmu-v3: Convert to domain_alloc_sva() Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc() Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
2024-06-01 21:08 ` Jason Gunthorpe
2024-05-28 7:18 ` [PATCH v4 4/7] iommu/arm-smmu-v3: Add feature detection for HTTU Shameer Kolothum
` (3 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
This will be used by iommufd for allocating usr managed domains and is
also required when we add support for iommufd based dirty tracking
support.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +++++++++++++++++++--
1 file changed, 31 insertions(+), 2 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 b574a36a7b95..b72a4f68ecd9 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -36,6 +36,8 @@ module_param(disable_msipolling, bool, 0444);
MODULE_PARM_DESC(disable_msipolling,
"Disable MSI-based polling for CMD_SYNC completion.");
+static struct iommu_ops arm_smmu_ops;
+
enum arm_smmu_msi_index {
EVTQ_MSI_INDEX,
GERROR_MSI_INDEX,
@@ -2715,6 +2717,34 @@ static struct iommu_domain arm_smmu_blocked_domain = {
.ops = &arm_smmu_blocked_ops,
};
+static struct iommu_domain *
+arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
+ struct iommu_domain *parent,
+ const struct iommu_user_data *user_data)
+{
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ struct arm_smmu_domain *smmu_domain;
+ int ret;
+
+ if (flags || parent || user_data)
+ return ERR_PTR(-EINVAL);
+
+ smmu_domain = arm_smmu_domain_alloc();
+ if (!smmu_domain)
+ return ERR_PTR(-ENOMEM);
+
+ 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);
+ if (ret)
+ goto err_free;
+ return &smmu_domain->domain;
+
+err_free:
+ kfree(smmu_domain);
+ return ERR_PTR(ret);
+}
+
static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t pgsize, size_t pgcount,
int prot, gfp_t gfp, size_t *mapped)
@@ -2885,8 +2915,6 @@ static void arm_smmu_remove_master(struct arm_smmu_master *master)
kfree(master->streams);
}
-static struct iommu_ops arm_smmu_ops;
-
static struct iommu_device *arm_smmu_probe_device(struct device *dev)
{
int ret;
@@ -3101,6 +3129,7 @@ static struct iommu_ops arm_smmu_ops = {
.blocked_domain = &arm_smmu_blocked_domain,
.capable = arm_smmu_capable,
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
+ .domain_alloc_user = arm_smmu_domain_alloc_user,
.domain_alloc_sva = arm_smmu_sva_domain_alloc,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 4/7] iommu/arm-smmu-v3: Add feature detection for HTTU
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
` (2 preceding siblings ...)
2024-05-28 7:18 ` [PATCH v4 3/7] iommu/arm-smmu-v3: Add support for domain_alloc_user fn Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 5/7] iommu/io-pgtable-arm: Add read_and_clear_dirty() support Shameer Kolothum
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
If the SMMU supports it and the kernel was built with HTTU support,
Probe support for Hardware Translation Table Update (HTTU) which is
essentially to enable hardware update of access and dirty flags.
Probe and set the smmu::features for Hardware Dirty and Hardware Access
bits. This is in preparation, to enable it on the context descriptors of
stage 1 format.
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +++++++++++++++++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 5 ++++
2 files changed, 38 insertions(+)
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 b72a4f68ecd9..392e7e3601ea 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3730,6 +3730,29 @@ static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
}
}
+static void arm_smmu_get_httu(struct arm_smmu_device *smmu, u32 reg)
+{
+ u32 fw_features = smmu->features & (ARM_SMMU_FEAT_HA | ARM_SMMU_FEAT_HD);
+ u32 httu = FIELD_GET(IDR0_HTTU, reg);
+ u32 features = 0;
+
+ switch (httu) {
+ case IDR0_HTTU_ACCESS_DIRTY:
+ features |= ARM_SMMU_FEAT_HD;
+ fallthrough;
+ case IDR0_HTTU_ACCESS:
+ features |= ARM_SMMU_FEAT_HA;
+ }
+
+ if (smmu->dev->of_node)
+ smmu->features |= features;
+ else if (features != fw_features)
+ /* ACPI IORT sets the HTTU bits */
+ dev_warn(smmu->dev,
+ "IDR0.HTTU(0x%x) overridden by FW configuration (0x%x)\n",
+ httu, fw_features);
+}
+
static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
{
u32 reg;
@@ -3790,6 +3813,8 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
smmu->features |= ARM_SMMU_FEAT_E2H;
}
+ arm_smmu_get_httu(smmu, reg);
+
/*
* The coherency feature as set by FW is used in preference to the ID
* register, but warn on mismatch.
@@ -3985,6 +4010,14 @@ static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+ switch (FIELD_GET(ACPI_IORT_SMMU_V3_HTTU_OVERRIDE, iort_smmu->flags)) {
+ case IDR0_HTTU_ACCESS_DIRTY:
+ smmu->features |= ARM_SMMU_FEAT_HD;
+ fallthrough;
+ case IDR0_HTTU_ACCESS:
+ smmu->features |= ARM_SMMU_FEAT_HA;
+ }
+
return 0;
}
#else
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index e67ce0f8867f..ac61b4c0a612 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -33,6 +33,9 @@
#define IDR0_ASID16 (1 << 12)
#define IDR0_ATS (1 << 10)
#define IDR0_HYP (1 << 9)
+#define IDR0_HTTU GENMASK(7, 6)
+#define IDR0_HTTU_ACCESS 1
+#define IDR0_HTTU_ACCESS_DIRTY 2
#define IDR0_COHACC (1 << 4)
#define IDR0_TTF GENMASK(3, 2)
#define IDR0_TTF_AARCH64 2
@@ -648,6 +651,8 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_E2H (1 << 18)
#define ARM_SMMU_FEAT_NESTING (1 << 19)
#define ARM_SMMU_FEAT_ATTR_TYPES_OVR (1 << 20)
+#define ARM_SMMU_FEAT_HA (1 << 21)
+#define ARM_SMMU_FEAT_HD (1 << 22)
u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 5/7] iommu/io-pgtable-arm: Add read_and_clear_dirty() support
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
` (3 preceding siblings ...)
2024-05-28 7:18 ` [PATCH v4 4/7] iommu/arm-smmu-v3: Add feature detection for HTTU Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
2024-06-01 21:17 ` Jason Gunthorpe
2024-05-28 7:18 ` [PATCH v4 6/7] iommu/arm-smmu-v3: Add support for dirty tracking in domain alloc Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 7/7] iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping Shameer Kolothum
6 siblings, 1 reply; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
.read_and_clear_dirty() IOMMU domain op takes care of reading the dirty
bits (i.e. PTE has DBM set and AP[2] clear) and marshalling into a
bitmap of a given page size.
While reading the dirty bits we also set the PTE AP[2] bit to mark it
as writeable-clean depending on read_and_clear_dirty() flags.
PTE states with respect to DBM bit:
DBM bit AP[2]("RDONLY" bit)
1. writable_clean 1 1
2. writable_dirty 1 0
3. read-only 0 1
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
drivers/iommu/io-pgtable-arm.c | 114 ++++++++++++++++++++++++++++++++-
1 file changed, 112 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 3d23b924cec1..2e57e8616387 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -76,6 +76,7 @@
#define ARM_LPAE_PTE_NSTABLE (((arm_lpae_iopte)1) << 63)
#define ARM_LPAE_PTE_XN (((arm_lpae_iopte)3) << 53)
+#define ARM_LPAE_PTE_DBM (((arm_lpae_iopte)1) << 51)
#define ARM_LPAE_PTE_AF (((arm_lpae_iopte)1) << 10)
#define ARM_LPAE_PTE_SH_NS (((arm_lpae_iopte)0) << 8)
#define ARM_LPAE_PTE_SH_OS (((arm_lpae_iopte)2) << 8)
@@ -85,7 +86,7 @@
#define ARM_LPAE_PTE_ATTR_LO_MASK (((arm_lpae_iopte)0x3ff) << 2)
/* Ignore the contiguous bit for block splitting */
-#define ARM_LPAE_PTE_ATTR_HI_MASK (((arm_lpae_iopte)6) << 52)
+#define ARM_LPAE_PTE_ATTR_HI_MASK (ARM_LPAE_PTE_XN | ARM_LPAE_PTE_DBM)
#define ARM_LPAE_PTE_ATTR_MASK (ARM_LPAE_PTE_ATTR_LO_MASK | \
ARM_LPAE_PTE_ATTR_HI_MASK)
/* Software bit for solving coherency races */
@@ -93,7 +94,11 @@
/* Stage-1 PTE */
#define ARM_LPAE_PTE_AP_UNPRIV (((arm_lpae_iopte)1) << 6)
-#define ARM_LPAE_PTE_AP_RDONLY (((arm_lpae_iopte)2) << 6)
+#define ARM_LPAE_PTE_AP_RDONLY_BIT 7
+#define ARM_LPAE_PTE_AP_RDONLY (((arm_lpae_iopte)1) << \
+ ARM_LPAE_PTE_AP_RDONLY_BIT)
+#define ARM_LPAE_PTE_AP_WR_CLEAN_MASK (ARM_LPAE_PTE_AP_RDONLY | \
+ ARM_LPAE_PTE_DBM)
#define ARM_LPAE_PTE_ATTRINDX_SHIFT 2
#define ARM_LPAE_PTE_nG (((arm_lpae_iopte)1) << 11)
@@ -139,6 +144,12 @@
#define iopte_prot(pte) ((pte) & ARM_LPAE_PTE_ATTR_MASK)
+#define iopte_writeable_dirty(pte) \
+ (((pte) & ARM_LPAE_PTE_AP_WR_CLEAN_MASK) == ARM_LPAE_PTE_DBM)
+
+#define iopte_set_writeable_clean(ptep) \
+ set_bit(ARM_LPAE_PTE_AP_RDONLY_BIT, (unsigned long *)(ptep))
+
struct arm_lpae_io_pgtable {
struct io_pgtable iop;
@@ -160,6 +171,13 @@ static inline bool iopte_leaf(arm_lpae_iopte pte, int lvl,
return iopte_type(pte) == ARM_LPAE_PTE_TYPE_BLOCK;
}
+static inline bool iopte_table(arm_lpae_iopte pte, int lvl)
+{
+ if (lvl == (ARM_LPAE_MAX_LEVELS - 1))
+ return false;
+ return iopte_type(pte) == ARM_LPAE_PTE_TYPE_TABLE;
+}
+
static arm_lpae_iopte paddr_to_iopte(phys_addr_t paddr,
struct arm_lpae_io_pgtable *data)
{
@@ -726,6 +744,97 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
return iopte_to_paddr(pte, data) | iova;
}
+struct io_pgtable_walk_data {
+ struct iommu_dirty_bitmap *dirty;
+ unsigned long flags;
+ u64 addr;
+ const u64 end;
+};
+
+static int __arm_lpae_iopte_walk_dirty(struct arm_lpae_io_pgtable *data,
+ struct io_pgtable_walk_data *walk_data,
+ arm_lpae_iopte *ptep,
+ int lvl);
+
+static int io_pgtable_visit_dirty(struct arm_lpae_io_pgtable *data,
+ struct io_pgtable_walk_data *walk_data,
+ arm_lpae_iopte *ptep, int lvl)
+{
+ struct io_pgtable *iop = &data->iop;
+ arm_lpae_iopte pte = READ_ONCE(*ptep);
+
+ if (iopte_leaf(pte, lvl, iop->fmt)) {
+ size_t size = ARM_LPAE_BLOCK_SIZE(lvl, data);
+
+ if (iopte_writeable_dirty(pte)) {
+ iommu_dirty_bitmap_record(walk_data->dirty,
+ walk_data->addr, size);
+ if (!(walk_data->flags & IOMMU_DIRTY_NO_CLEAR))
+ iopte_set_writeable_clean(ptep);
+ }
+ walk_data->addr += size;
+ return 0;
+ }
+
+ if (WARN_ON(!iopte_table(pte, lvl)))
+ return -EINVAL;
+
+ ptep = iopte_deref(pte, data);
+ return __arm_lpae_iopte_walk_dirty(data, walk_data, ptep, lvl + 1);
+}
+
+static int __arm_lpae_iopte_walk_dirty(struct arm_lpae_io_pgtable *data,
+ struct io_pgtable_walk_data *walk_data,
+ arm_lpae_iopte *ptep,
+ int lvl)
+{
+ u32 idx;
+ int max_entries, ret;
+
+ if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS))
+ return -EINVAL;
+
+ if (lvl == data->start_level)
+ max_entries = ARM_LPAE_PGD_SIZE(data) / sizeof(arm_lpae_iopte);
+ else
+ max_entries = ARM_LPAE_PTES_PER_TABLE(data);
+
+ for (idx = ARM_LPAE_LVL_IDX(walk_data->addr, lvl, data);
+ (idx < max_entries) && (walk_data->addr < walk_data->end); ++idx) {
+ ret = io_pgtable_visit_dirty(data, walk_data, ptep + idx, lvl);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int arm_lpae_read_and_clear_dirty(struct io_pgtable_ops *ops,
+ unsigned long iova, size_t size,
+ unsigned long flags,
+ struct iommu_dirty_bitmap *dirty)
+{
+ struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ struct io_pgtable_cfg *cfg = &data->iop.cfg;
+ struct io_pgtable_walk_data walk_data = {
+ .dirty = dirty,
+ .flags = flags,
+ .addr = iova,
+ .end = iova + size,
+ };
+ arm_lpae_iopte *ptep = data->pgd;
+ int lvl = data->start_level;
+
+ if (WARN_ON(!size))
+ return -EINVAL;
+ if (WARN_ON((iova + size - 1) & ~(BIT(cfg->ias) - 1)))
+ return -EINVAL;
+ if (data->iop.fmt != ARM_64_LPAE_S1)
+ return -EINVAL;
+
+ return __arm_lpae_iopte_walk_dirty(data, &walk_data, ptep, lvl);
+}
+
static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
{
unsigned long granule, page_sizes;
@@ -804,6 +913,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
.map_pages = arm_lpae_map_pages,
.unmap_pages = arm_lpae_unmap_pages,
.iova_to_phys = arm_lpae_iova_to_phys,
+ .read_and_clear_dirty = arm_lpae_read_and_clear_dirty,
};
return data;
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 6/7] iommu/arm-smmu-v3: Add support for dirty tracking in domain alloc
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
` (4 preceding siblings ...)
2024-05-28 7:18 ` [PATCH v4 5/7] iommu/io-pgtable-arm: Add read_and_clear_dirty() support Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 7/7] iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping Shameer Kolothum
6 siblings, 0 replies; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
From: Joao Martins <joao.m.martins@oracle.com>
This provides all the infrastructure to enable dirty tracking if the
hardware has the capability and domain alloc request for it.
Also, add a device_iommu_capable() check in iommufd core for
IOMMU_CAP_DIRTY_TRACKING before we request a user domain with dirty
tracking support.
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 <joao.m.martins@oracle.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 82 +++++++++++++++------
drivers/iommu/iommufd/hw_pagetable.c | 3 +
include/linux/io-pgtable.h | 4 +
3 files changed, 67 insertions(+), 22 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 392e7e3601ea..b91c995cf9ae 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -27,6 +27,7 @@
#include <linux/pci-ats.h>
#include <linux/platform_device.h>
#include <kunit/visibility.h>
+#include <uapi/linux/iommufd.h>
#include "arm-smmu-v3.h"
#include "../../dma-iommu.h"
@@ -37,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,
@@ -82,7 +84,7 @@ 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 parse_driver_options(struct arm_smmu_device *smmu)
@@ -2272,7 +2274,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);
@@ -2338,15 +2340,15 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_device *smmu,
}
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;
int (*finalise_stage_fn)(struct arm_smmu_device *smmu,
struct arm_smmu_domain *smmu_domain);
+ 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))
@@ -2354,17 +2356,31 @@ 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;
+ case ARM_SMMU_DOMAIN_S1: {
+ 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;
finalise_stage_fn = arm_smmu_domain_finalise_s1;
break;
+ }
case ARM_SMMU_DOMAIN_S2:
- ias = smmu->ias;
- oas = smmu->oas;
+ if (enable_dirty)
+ return -EOPNOTSUPP;
+ pgtbl_cfg.ias = smmu->ias;
+ pgtbl_cfg.oas = smmu->oas;
fmt = ARM_64_LPAE_S2;
finalise_stage_fn = arm_smmu_domain_finalise_s2;
break;
@@ -2372,15 +2388,6 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain,
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;
@@ -2388,6 +2395,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 = finalise_stage_fn(smmu, smmu_domain);
if (ret < 0) {
@@ -2592,7 +2601,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;
@@ -2723,10 +2732,13 @@ 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_DIRTY_TRACKING;
struct arm_smmu_domain *smmu_domain;
int ret;
- if (flags || parent || user_data)
+ if (flags & ~PAGING_FLAGS)
+ return ERR_PTR(-EOPNOTSUPP);
+ if (parent || user_data)
return ERR_PTR(-EINVAL);
smmu_domain = arm_smmu_domain_alloc();
@@ -2735,7 +2747,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;
@@ -2992,6 +3004,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;
@@ -3155,6 +3188,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/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index 33d142f8057d..6d5b2fffeea0 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -114,6 +114,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
return ERR_PTR(-EOPNOTSUPP);
if (flags & ~valid_flags)
return ERR_PTR(-EOPNOTSUPP);
+ if ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) &&
+ !device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING))
+ return ERR_PTR(-EOPNOTSUPP);
hwpt_paging = __iommufd_object_alloc(
ictx, hwpt_paging, IOMMUFD_OBJ_HWPT_PAGING, common.obj);
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;
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 7/7] iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
` (5 preceding siblings ...)
2024-05-28 7:18 ` [PATCH v4 6/7] iommu/arm-smmu-v3: Add support for dirty tracking in domain alloc Shameer Kolothum
@ 2024-05-28 7:18 ` Shameer Kolothum
6 siblings, 0 replies; 12+ messages in thread
From: Shameer Kolothum @ 2024-05-28 7:18 UTC (permalink / raw)
To: iommu, linux-arm-kernel
Cc: robin.murphy, will, joro, jgg, ryan.roberts, kevin.tian, nicolinc,
mshavit, eric.auger, joao.m.martins, jiangkunkun, zhukeqian1,
linuxarm
From: Kunkun Jiang <jiangkunkun@huawei.com>
If io-pgtable quirk flag indicates support for hardware update of
dirty state, enable HA/HD bits in the SMMU CD and also set the DBM
bit in the page descriptor.
Now report the dirty page tracking capability of SMMUv3 and
select IOMMUFD_DRIVER for ARM_SMMU_V3 if IOMMUFD is enabled.
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
drivers/iommu/Kconfig | 1 +
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 15 +++++++++++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 +++
drivers/iommu/io-pgtable-arm.c | 5 ++++-
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index c04584be3089..a82f10054aec 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -394,6 +394,7 @@ config ARM_SMMU_V3
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select GENERIC_MSI_IRQ
+ select IOMMUFD_DRIVER if IOMMUFD
help
Support for implementations of the ARM System MMU architecture
version 3 providing translation support to a PCIe root complex.
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 b91c995cf9ae..be1b067c6a1c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1335,6 +1335,12 @@ void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
CTXDESC_CD_0_ASET |
FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid)
);
+
+ /* To enable dirty flag update, set both Access flag and dirty state update */
+ if (pgtbl_cfg->quirks & IO_PGTABLE_QUIRK_ARM_HD)
+ target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HA |
+ CTXDESC_CD_0_TCR_HD);
+
target->data[1] = cpu_to_le64(pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
CTXDESC_CD_1_TTB0_MASK);
target->data[3] = cpu_to_le64(pgtbl_cfg->arm_lpae_s1_cfg.mair);
@@ -2224,6 +2230,13 @@ static const struct iommu_flush_ops arm_smmu_flush_ops = {
.tlb_add_page = arm_smmu_tlb_inv_page_nosync,
};
+static bool arm_smmu_dbm_capable(struct arm_smmu_device *smmu)
+{
+ u32 features = (ARM_SMMU_FEAT_HD | ARM_SMMU_FEAT_COHERENCY);
+
+ return (smmu->features & features) == features;
+}
+
/* IOMMU API */
static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
{
@@ -2236,6 +2249,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
case IOMMU_CAP_NOEXEC:
case IOMMU_CAP_DEFERRED_FLUSH:
return true;
+ case IOMMU_CAP_DIRTY_TRACKING:
+ return arm_smmu_dbm_capable(master->smmu);
default:
return false;
}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index ac61b4c0a612..530f951bdf40 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -304,6 +304,9 @@ struct arm_smmu_cd {
#define CTXDESC_CD_0_TCR_IPS GENMASK_ULL(34, 32)
#define CTXDESC_CD_0_TCR_TBI0 (1ULL << 38)
+#define CTXDESC_CD_0_TCR_HA (1UL << 43)
+#define CTXDESC_CD_0_TCR_HD (1UL << 42)
+
#define CTXDESC_CD_0_AA64 (1UL << 41)
#define CTXDESC_CD_0_S (1UL << 44)
#define CTXDESC_CD_0_R (1UL << 45)
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 2e57e8616387..f5d9fd1f45bf 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -440,6 +440,8 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
pte = ARM_LPAE_PTE_nG;
if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
pte |= ARM_LPAE_PTE_AP_RDONLY;
+ else if (data->iop.cfg.quirks & IO_PGTABLE_QUIRK_ARM_HD)
+ pte |= ARM_LPAE_PTE_DBM;
if (!(prot & IOMMU_PRIV))
pte |= ARM_LPAE_PTE_AP_UNPRIV;
} else {
@@ -929,7 +931,8 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
IO_PGTABLE_QUIRK_ARM_TTBR1 |
- IO_PGTABLE_QUIRK_ARM_OUTER_WBWA))
+ IO_PGTABLE_QUIRK_ARM_OUTER_WBWA |
+ IO_PGTABLE_QUIRK_ARM_HD))
return NULL;
data = arm_lpae_alloc_pgtable(cfg);
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc()
2024-05-28 7:18 ` [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc() Shameer Kolothum
@ 2024-06-01 21:06 ` Jason Gunthorpe
2024-06-05 15:19 ` Shameerali Kolothum Thodi
0 siblings, 1 reply; 12+ messages in thread
From: Jason Gunthorpe @ 2024-06-01 21:06 UTC (permalink / raw)
To: Shameer Kolothum
Cc: iommu, linux-arm-kernel, robin.murphy, will, joro, ryan.roberts,
kevin.tian, nicolinc, mshavit, eric.auger, joao.m.martins,
jiangkunkun, zhukeqian1, linuxarm
On Tue, May 28, 2024 at 08:18:26AM +0100, Shameer Kolothum wrote:
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> @@ -648,7 +648,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
>
> static void arm_smmu_sva_domain_free(struct iommu_domain *domain)
> {
> - kfree(domain);
> + kfree(to_smmu_domain(domain));
> }
> @@ -659,13 +659,16 @@ static const struct iommu_domain_ops arm_smmu_sva_domain_ops = {
> struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
> struct mm_struct *mm)
> {
> - struct iommu_domain *domain;
> + struct arm_smmu_master *master = dev_iommu_priv_get(dev);
> + struct arm_smmu_device *smmu = master->smmu;
> + struct arm_smmu_domain *smmu_domain;
>
> - domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> - if (!domain)
> - return ERR_PTR(-ENOMEM);
> - domain->type = IOMMU_DOMAIN_SVA;
> - domain->ops = &arm_smmu_sva_domain_ops;
> + smmu_domain = arm_smmu_domain_alloc();
> + if (IS_ERR(smmu_domain))
> + return ERR_CAST(smmu_domain);
> + smmu_domain->domain.type = IOMMU_DOMAIN_SVA;
> + smmu_domain->domain.ops = &arm_smmu_sva_domain_ops;
> + smmu_domain->smmu = smmu;
>
> - return domain;
> + return &smmu_domain->domain;
> }
If you drop these two hunks you can drop the first patch as well. There
is no need to touch SVA in this series
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 3/7] iommu/arm-smmu-v3: Add support for domain_alloc_user fn
2024-05-28 7:18 ` [PATCH v4 3/7] iommu/arm-smmu-v3: Add support for domain_alloc_user fn Shameer Kolothum
@ 2024-06-01 21:08 ` Jason Gunthorpe
0 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2024-06-01 21:08 UTC (permalink / raw)
To: Shameer Kolothum
Cc: iommu, linux-arm-kernel, robin.murphy, will, joro, ryan.roberts,
kevin.tian, nicolinc, mshavit, eric.auger, joao.m.martins,
jiangkunkun, zhukeqian1, linuxarm
On Tue, May 28, 2024 at 08:18:27AM +0100, Shameer Kolothum wrote:
> @@ -2715,6 +2717,34 @@ static struct iommu_domain arm_smmu_blocked_domain = {
> .ops = &arm_smmu_blocked_ops,
> };
>
> +static struct iommu_domain *
> +arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
> + struct iommu_domain *parent,
> + const struct iommu_user_data *user_data)
> +{
> + struct arm_smmu_master *master = dev_iommu_priv_get(dev);
> + struct arm_smmu_domain *smmu_domain;
> + int ret;
> +
> + if (flags || parent || user_data)
> + return ERR_PTR(-EINVAL);
This should be EOPNOTSUPP, and same in the following patch that
touches this.
Otherwise looks good
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 5/7] iommu/io-pgtable-arm: Add read_and_clear_dirty() support
2024-05-28 7:18 ` [PATCH v4 5/7] iommu/io-pgtable-arm: Add read_and_clear_dirty() support Shameer Kolothum
@ 2024-06-01 21:17 ` Jason Gunthorpe
0 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2024-06-01 21:17 UTC (permalink / raw)
To: Shameer Kolothum
Cc: iommu, linux-arm-kernel, robin.murphy, will, joro, ryan.roberts,
kevin.tian, nicolinc, mshavit, eric.auger, joao.m.martins,
jiangkunkun, zhukeqian1, linuxarm
On Tue, May 28, 2024 at 08:18:29AM +0100, Shameer Kolothum wrote:
> .read_and_clear_dirty() IOMMU domain op takes care of reading the dirty
> bits (i.e. PTE has DBM set and AP[2] clear) and marshalling into a
> bitmap of a given page size.
>
> While reading the dirty bits we also set the PTE AP[2] bit to mark it
> as writeable-clean depending on read_and_clear_dirty() flags.
>
> PTE states with respect to DBM bit:
>
> DBM bit AP[2]("RDONLY" bit)
> 1. writable_clean 1 1
> 2. writable_dirty 1 0
> 3. read-only 0 1
>
> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> drivers/iommu/io-pgtable-arm.c | 114 ++++++++++++++++++++++++++++++++-
> 1 file changed, 112 insertions(+), 2 deletions(-)
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc()
2024-06-01 21:06 ` Jason Gunthorpe
@ 2024-06-05 15:19 ` Shameerali Kolothum Thodi
0 siblings, 0 replies; 12+ messages in thread
From: Shameerali Kolothum Thodi @ 2024-06-05 15:19 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
robin.murphy@arm.com, will@kernel.org, joro@8bytes.org,
ryan.roberts@arm.com, kevin.tian@intel.com, nicolinc@nvidia.com,
mshavit@google.com, eric.auger@redhat.com,
joao.m.martins@oracle.com, jiangkunkun, zhukeqian, Linuxarm
> -----Original Message-----
> From: Jason Gunthorpe <jgg@nvidia.com>
> Sent: Saturday, June 1, 2024 10:07 PM
> To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> Cc: iommu@lists.linux.dev; linux-arm-kernel@lists.infradead.org;
> robin.murphy@arm.com; will@kernel.org; joro@8bytes.org;
> ryan.roberts@arm.com; kevin.tian@intel.com; nicolinc@nvidia.com;
> mshavit@google.com; eric.auger@redhat.com; joao.m.martins@oracle.com;
> jiangkunkun <jiangkunkun@huawei.com>; zhukeqian
> <zhukeqian1@huawei.com>; Linuxarm <linuxarm@huawei.com>
> Subject: Re: [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common
> arm_smmu_domain_alloc()
>
> On Tue, May 28, 2024 at 08:18:26AM +0100, Shameer Kolothum wrote:
>
> > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> > @@ -648,7 +648,7 @@ static int arm_smmu_sva_set_dev_pasid(struct
> iommu_domain *domain,
> >
> > static void arm_smmu_sva_domain_free(struct iommu_domain *domain)
> > {
> > - kfree(domain);
> > + kfree(to_smmu_domain(domain));
> > }
>
>
> > @@ -659,13 +659,16 @@ static const struct iommu_domain_ops
> arm_smmu_sva_domain_ops = {
> > struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
> > struct mm_struct *mm)
> > {
> > - struct iommu_domain *domain;
> > + struct arm_smmu_master *master = dev_iommu_priv_get(dev);
> > + struct arm_smmu_device *smmu = master->smmu;
> > + struct arm_smmu_domain *smmu_domain;
> >
> > - domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> > - if (!domain)
> > - return ERR_PTR(-ENOMEM);
> > - domain->type = IOMMU_DOMAIN_SVA;
> > - domain->ops = &arm_smmu_sva_domain_ops;
> > + smmu_domain = arm_smmu_domain_alloc();
> > + if (IS_ERR(smmu_domain))
> > + return ERR_CAST(smmu_domain);
> > + smmu_domain->domain.type = IOMMU_DOMAIN_SVA;
> > + smmu_domain->domain.ops = &arm_smmu_sva_domain_ops;
> > + smmu_domain->smmu = smmu;
> >
> > - return domain;
> > + return &smmu_domain->domain;
> > }
>
> If you drop these two hunks you can drop the first patch as well. There
> is no need to touch SVA in this series
That is right. I will make those changes and re-spin soon.
Thanks,
SHameer
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-06-05 15:22 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-28 7:18 [PATCH v4 0/7] iommu/smmuv3: Add IOMMUFD dirty tracking support for SMMUv3 Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 1/7] iommu/arm-smmu-v3: Convert to domain_alloc_sva() Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 2/7] iommu/arm-smmu-v3: Factor out a common arm_smmu_domain_alloc() Shameer Kolothum
2024-06-01 21:06 ` Jason Gunthorpe
2024-06-05 15:19 ` Shameerali Kolothum Thodi
2024-05-28 7:18 ` [PATCH v4 3/7] iommu/arm-smmu-v3: Add support for domain_alloc_user fn Shameer Kolothum
2024-06-01 21:08 ` Jason Gunthorpe
2024-05-28 7:18 ` [PATCH v4 4/7] iommu/arm-smmu-v3: Add feature detection for HTTU Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 5/7] iommu/io-pgtable-arm: Add read_and_clear_dirty() support Shameer Kolothum
2024-06-01 21:17 ` Jason Gunthorpe
2024-05-28 7:18 ` [PATCH v4 6/7] iommu/arm-smmu-v3: Add support for dirty tracking in domain alloc Shameer Kolothum
2024-05-28 7:18 ` [PATCH v4 7/7] iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping Shameer Kolothum
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).