[PATCH v6 6/6] iommu/tegra-smmu: Add pagetable mappings to debugfs
This patch dumps all active mapping entries from pagetable to a debugfs directory named "mappings". Attaching an example: SWGROUP: hc as->id: 0 as->attr: R|W|N as->pd_dma: 0x80c03000 { [index: 1023] 0xf0080c3e (count: 2) { PTE RANGE | ATTR | PHYS | IOVA | SIZE [#1022, #1023] | 0x5 | 0x00010bbf1000 | 0xe000 | 0x2000 } } Total PDE count: 1 Total PTE count: 2 Signed-off-by: Nicolin Chen --- drivers/iommu/tegra-smmu.c | 145 + 1 file changed, 145 insertions(+) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 68c34a4a0ecc..aac977e181f6 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -46,6 +46,7 @@ struct tegra_smmu { struct list_head list; struct dentry *debugfs; + struct dentry *debugfs_mappings; struct iommu_device iommu; /* IOMMU Core code handle */ }; @@ -153,6 +154,9 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset) #define SMMU_PDE_ATTR (SMMU_PDE_READABLE | SMMU_PDE_WRITABLE | \ SMMU_PDE_NONSECURE) +#define SMMU_PTE_ATTR (SMMU_PTE_READABLE | SMMU_PTE_WRITABLE | \ +SMMU_PTE_NONSECURE) +#define SMMU_PTE_ATTR_SHIFT29 static unsigned int iova_pd_index(unsigned long iova) { @@ -164,6 +168,12 @@ static unsigned int iova_pt_index(unsigned long iova) return (iova >> SMMU_PTE_SHIFT) & (SMMU_NUM_PTE - 1); } +static unsigned long pd_pt_index_iova(unsigned int pd_index, unsigned int pt_index) +{ + return ((dma_addr_t)pd_index & (SMMU_NUM_PDE - 1)) << SMMU_PDE_SHIFT | + ((dma_addr_t)pt_index & (SMMU_NUM_PTE - 1)) << SMMU_PTE_SHIFT; +} + static bool smmu_dma_addr_valid(struct tegra_smmu *smmu, dma_addr_t addr) { addr >>= 12; @@ -496,6 +506,8 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, mutex_unlock(&smmu->lock); } +static const struct file_operations tegra_smmu_debugfs_mappings_fops; + static void tegra_smmu_attach_as(struct tegra_smmu *smmu, struct tegra_smmu_as *as, unsigned int swgroup) @@ -517,6 +529,12 @@ static void tegra_smmu_attach_as(struct tegra_smmu *smmu, dev_warn(smmu->dev, "overwriting group->as for swgroup: %s\n", swgrp->name); group->as = as; + + if (smmu->debugfs_mappings) + debugfs_create_file(group->swgrp->name, 0444, + smmu->debugfs_mappings, group, + &tegra_smmu_debugfs_mappings_fops); + break; } @@ -541,6 +559,12 @@ static void tegra_smmu_detach_as(struct tegra_smmu *smmu, if (group->swgrp != swgrp) continue; group->as = NULL; + + if (smmu->debugfs_mappings) { + d = debugfs_lookup(group->swgrp->name, smmu->debugfs_mappings); + debugfs_remove(d); + } + break; } @@ -1124,6 +1148,125 @@ static int tegra_smmu_clients_show(struct seq_file *s, void *data) DEFINE_SHOW_ATTRIBUTE(tegra_smmu_clients); +static int tegra_smmu_debugfs_mappings_show(struct seq_file *s, void *data) +{ + struct tegra_smmu_group *group = s->private; + const struct tegra_smmu_swgroup *swgrp; + struct tegra_smmu_as *as; + struct tegra_smmu *smmu; + unsigned int pd_index; + unsigned int pt_index; + unsigned long flags; + u64 pte_count = 0; + u32 pde_count = 0; + u32 *pd, val; + + if (!group || !group->as || !group->swgrp) + return 0; + + swgrp = group->swgrp; + smmu = group->smmu; + as = group->as; + + mutex_lock(&smmu->lock); + + val = smmu_readl(smmu, swgrp->reg) & SMMU_ASID_ENABLE; + if (!val) + goto unlock; + + pd = page_address(as->pd); + if (!pd) + goto unlock; + + seq_printf(s, "\nSWGROUP: %s\n", swgrp->name); + seq_printf(s, "as->id: %d\nas->attr: %c|%c|%s\nas->pd_dma: %pad\n", as->id, + as->attr & SMMU_PD_READABLE ? 'R' : '-', + as->attr & SMMU_PD_WRITABLE ? 'W' : '-', + as->attr & SMMU_PD_NONSECURE ? "NS" : "S", + &as->pd_dma); + seq_puts(s, "{\n"); + + spin_lock_irqsave(&as->lock, flags); + + for (pd_index = 0; pd_index < SMMU_NUM_PDE; pd_index++) { + struct page *pt_page; + unsigned int i; + u32 *addr; + + /* An empty PDE should not have a pte use count */ + WARN_ON_ONCE(!pd[pd_index] ^ !as->count[pd_index]); + +
[PATCH v6 5/6] iommu/tegra-smmu: Attach as pointer to tegra_smmu_group
This could ease driver to access corresponding as pointer when having tegra_smmu_group pointer only, which can help new mappings debugfs nodes. Also moving tegra_smmu_find_group_soc() upward, for using it in new tegra_smmu_attach_as(); and it's better to have all tegra_smmu_find_* functions together. Signed-off-by: Nicolin Chen --- drivers/iommu/tegra-smmu.c | 94 +++--- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 8fd4985ac91e..68c34a4a0ecc 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -24,6 +24,7 @@ struct tegra_smmu_group { struct tegra_smmu *smmu; const struct tegra_smmu_group_soc *group_soc; const struct tegra_smmu_swgroup *swgrp; + struct tegra_smmu_as *as; struct iommu_group *grp; }; @@ -349,6 +350,19 @@ tegra_smmu_find_swgrp(struct tegra_smmu *smmu, unsigned int swgroup) return swgrp; } +static const struct tegra_smmu_group_soc * +tegra_smmu_find_group_soc(struct tegra_smmu *smmu, unsigned int swgroup) +{ + unsigned int i, j; + + for (i = 0; i < smmu->soc->num_groups; i++) + for (j = 0; j < smmu->soc->groups[i].num_swgroups; j++) + if (smmu->soc->groups[i].swgroups[j] == swgroup) + return &smmu->soc->groups[i]; + + return NULL; +} + static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup, unsigned int asid) { @@ -482,6 +496,57 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, mutex_unlock(&smmu->lock); } +static void tegra_smmu_attach_as(struct tegra_smmu *smmu, +struct tegra_smmu_as *as, +unsigned int swgroup) +{ + const struct tegra_smmu_swgroup *swgrp; + struct tegra_smmu_group *group; + + /* Find swgrp according to the swgroup id */ + swgrp = tegra_smmu_find_swgrp(smmu, swgroup); + if (!swgrp) + return; + + mutex_lock(&smmu->lock); + + list_for_each_entry(group, &smmu->groups, list) { + if (group->swgrp != swgrp) + continue; + if (group->as) + dev_warn(smmu->dev, +"overwriting group->as for swgroup: %s\n", swgrp->name); + group->as = as; + break; + } + + mutex_unlock(&smmu->lock); +} + +static void tegra_smmu_detach_as(struct tegra_smmu *smmu, +unsigned int swgroup) +{ + const struct tegra_smmu_swgroup *swgrp; + struct tegra_smmu_group *group; + struct dentry *d; + + /* Find swgrp according to the swgroup id */ + swgrp = tegra_smmu_find_swgrp(smmu, swgroup); + if (!swgrp) + return; + + mutex_lock(&smmu->lock); + + list_for_each_entry(group, &smmu->groups, list) { + if (group->swgrp != swgrp) + continue; + group->as = NULL; + break; + } + + mutex_unlock(&smmu->lock); +} + static int tegra_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) { @@ -495,11 +560,15 @@ static int tegra_smmu_attach_dev(struct iommu_domain *domain, return -ENOENT; for (index = 0; index < fwspec->num_ids; index++) { + unsigned int swgroup = fwspec->ids[index]; + err = tegra_smmu_as_prepare(smmu, as); if (err) goto disable; - tegra_smmu_enable(smmu, fwspec->ids[index], as->id); + tegra_smmu_attach_as(smmu, as, swgroup); + + tegra_smmu_enable(smmu, swgroup, as->id); } if (index == 0) @@ -509,7 +578,10 @@ static int tegra_smmu_attach_dev(struct iommu_domain *domain, disable: while (index--) { - tegra_smmu_disable(smmu, fwspec->ids[index], as->id); + unsigned int swgroup = fwspec->ids[index]; + + tegra_smmu_disable(smmu, swgroup, as->id); + tegra_smmu_detach_as(smmu, swgroup); tegra_smmu_as_unprepare(smmu, as); } @@ -527,7 +599,10 @@ static void tegra_smmu_detach_dev(struct iommu_domain *domain, struct device *de return; for (index = 0; index < fwspec->num_ids; index++) { - tegra_smmu_disable(smmu, fwspec->ids[index], as->id); + unsigned int swgroup = fwspec->ids[index]; + + tegra_smmu_disable(smmu, swgroup, as->id); + tegra_smmu_detach_as(smmu, swgroup); tegra_smmu_as_unprepare(smmu, as); } } @@ -869,19 +944,6 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev) static void tegra_smmu_release_device(struct device *d
[PATCH v6 4/6] iommu/tegra-smmu: Use swgrp pointer instead of swgroup id
This patch changes in struct tegra_smmu_group to use swgrp pointer instead of swgroup, as a preparational change for the "mappings" debugfs feature. Signed-off-by: Nicolin Chen --- drivers/iommu/tegra-smmu.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 0f3883045ffa..8fd4985ac91e 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -23,8 +23,8 @@ struct tegra_smmu_group { struct list_head list; struct tegra_smmu *smmu; const struct tegra_smmu_group_soc *group_soc; + const struct tegra_smmu_swgroup *swgrp; struct iommu_group *grp; - unsigned int swgroup; }; struct tegra_smmu { @@ -897,18 +897,22 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); struct tegra_smmu *smmu = dev_iommu_priv_get(dev); const struct tegra_smmu_group_soc *group_soc; + const struct tegra_smmu_swgroup *swgrp; unsigned int swgroup = fwspec->ids[0]; struct tegra_smmu_group *group; struct iommu_group *grp; + /* Find swgrp according to the swgroup id */ + swgrp = tegra_smmu_find_swgrp(smmu, swgroup); + /* Find group_soc associating with swgroup */ group_soc = tegra_smmu_find_group_soc(smmu, swgroup); mutex_lock(&smmu->lock); - /* Find existing iommu_group associating with swgroup or group_soc */ + /* Find existing iommu_group associating with swgrp or group_soc */ list_for_each_entry(group, &smmu->groups, list) - if ((group->swgroup == swgroup) || + if ((swgrp && group->swgrp == swgrp) || (group_soc && group->group_soc == group_soc)) { grp = iommu_group_ref_get(group->grp); mutex_unlock(&smmu->lock); @@ -923,7 +927,7 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) INIT_LIST_HEAD(&group->list); group->group_soc = group_soc; - group->swgroup = swgroup; + group->swgrp = swgrp; group->smmu = smmu; if (dev_is_pci(dev)) -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 1/6] iommu/tegra-smmu: Rename struct iommu_group *group to *grp
There are a few structs using "group" for their pointer instances. This gets confusing sometimes. The instance of struct iommu_group is used in local function with an alias "grp", which can separate it from others. So this patch simply renames "group" to "grp" as a cleanup. Signed-off-by: Nicolin Chen --- drivers/iommu/tegra-smmu.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 0a281833f611..6ebae635d3aa 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -23,7 +23,7 @@ struct tegra_smmu_group { struct list_head list; struct tegra_smmu *smmu; const struct tegra_smmu_group_soc *soc; - struct iommu_group *group; + struct iommu_group *grp; unsigned int swgroup; }; @@ -909,7 +909,7 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) /* Find existing iommu_group associating with swgroup or group_soc */ list_for_each_entry(group, &smmu->groups, list) if ((group->swgroup == swgroup) || (soc && group->soc == soc)) { - grp = iommu_group_ref_get(group->group); + grp = iommu_group_ref_get(group->grp); mutex_unlock(&smmu->lock); return grp; } @@ -926,23 +926,23 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) group->soc = soc; if (dev_is_pci(dev)) - group->group = pci_device_group(dev); + group->grp = pci_device_group(dev); else - group->group = generic_device_group(dev); + group->grp = generic_device_group(dev); - if (IS_ERR(group->group)) { + if (IS_ERR(group->grp)) { devm_kfree(smmu->dev, group); mutex_unlock(&smmu->lock); return NULL; } - iommu_group_set_iommudata(group->group, group, tegra_smmu_group_release); + iommu_group_set_iommudata(group->grp, group, tegra_smmu_group_release); if (soc) - iommu_group_set_name(group->group, soc->name); + iommu_group_set_name(group->grp, soc->name); list_add_tail(&group->list, &smmu->groups); mutex_unlock(&smmu->lock); - return group->group; + return group->grp; } static int tegra_smmu_of_xlate(struct device *dev, -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 3/6] iommu/tegra-smmu: Rename struct tegra_smmu_swgroup *group to *swgrp
There are both tegra_smmu_swgroup and tegra_smmu_group structs using "group" for their pointer instances. This gets confusing to read the driver sometimes. So this patch renames "group" of struct tegra_smmu_swgroup to "swgrp" as a cleanup. Also renames its "find" function. Note that we already have "swgroup" being used for an unsigned int type variable that is inside struct tegra_smmu_swgroup, so it's not able to use "swgroup" but only something like "swgrp". Signed-off-by: Nicolin Chen --- drivers/iommu/tegra-smmu.c | 34 +- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index a32ed347e25d..0f3883045ffa 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -334,35 +334,35 @@ static void tegra_smmu_domain_free(struct iommu_domain *domain) } static const struct tegra_smmu_swgroup * -tegra_smmu_find_swgroup(struct tegra_smmu *smmu, unsigned int swgroup) +tegra_smmu_find_swgrp(struct tegra_smmu *smmu, unsigned int swgroup) { - const struct tegra_smmu_swgroup *group = NULL; + const struct tegra_smmu_swgroup *swgrp = NULL; unsigned int i; for (i = 0; i < smmu->soc->num_swgroups; i++) { if (smmu->soc->swgroups[i].swgroup == swgroup) { - group = &smmu->soc->swgroups[i]; + swgrp = &smmu->soc->swgroups[i]; break; } } - return group; + return swgrp; } static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup, unsigned int asid) { - const struct tegra_smmu_swgroup *group; + const struct tegra_smmu_swgroup *swgrp; unsigned int i; u32 value; - group = tegra_smmu_find_swgroup(smmu, swgroup); - if (group) { - value = smmu_readl(smmu, group->reg); + swgrp = tegra_smmu_find_swgrp(smmu, swgroup); + if (swgrp) { + value = smmu_readl(smmu, swgrp->reg); value &= ~SMMU_ASID_MASK; value |= SMMU_ASID_VALUE(asid); value |= SMMU_ASID_ENABLE; - smmu_writel(smmu, value, group->reg); + smmu_writel(smmu, value, swgrp->reg); } else { pr_warn("%s group from swgroup %u not found\n", __func__, swgroup); @@ -385,17 +385,17 @@ static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup, static void tegra_smmu_disable(struct tegra_smmu *smmu, unsigned int swgroup, unsigned int asid) { - const struct tegra_smmu_swgroup *group; + const struct tegra_smmu_swgroup *swgrp; unsigned int i; u32 value; - group = tegra_smmu_find_swgroup(smmu, swgroup); - if (group) { - value = smmu_readl(smmu, group->reg); + swgrp = tegra_smmu_find_swgrp(smmu, swgroup); + if (swgrp) { + value = smmu_readl(smmu, swgrp->reg); value &= ~SMMU_ASID_MASK; value |= SMMU_ASID_VALUE(asid); value &= ~SMMU_ASID_ENABLE; - smmu_writel(smmu, value, group->reg); + smmu_writel(smmu, value, swgrp->reg); } for (i = 0; i < smmu->soc->num_clients; i++) { @@ -1008,11 +1008,11 @@ static int tegra_smmu_swgroups_show(struct seq_file *s, void *data) seq_printf(s, "\n"); for (i = 0; i < smmu->soc->num_swgroups; i++) { - const struct tegra_smmu_swgroup *group = &smmu->soc->swgroups[i]; + const struct tegra_smmu_swgroup *swgrp = &smmu->soc->swgroups[i]; const char *status; unsigned int asid; - value = smmu_readl(smmu, group->reg); + value = smmu_readl(smmu, swgrp->reg); if (value & SMMU_ASID_ENABLE) status = "yes"; @@ -1021,7 +1021,7 @@ static int tegra_smmu_swgroups_show(struct seq_file *s, void *data) asid = value & SMMU_ASID_MASK; - seq_printf(s, "%-9s %-7s %#04x\n", group->name, status, + seq_printf(s, "%-9s %-7s %#04x\n", swgrp->name, status, asid); } -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 2/6] iommu/tegra-smmu: Rename struct tegra_smmu_group_soc *soc to *group_soc
There are both tegra_smmu_soc and tegra_smmu_group_soc using "soc" for their pointer instances. This patch renames the one of struct tegra_smmu_group_soc from "soc" to "group_soc" to distinguish it. Signed-off-by: Nicolin Chen --- drivers/iommu/tegra-smmu.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 6ebae635d3aa..a32ed347e25d 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -22,7 +22,7 @@ struct tegra_smmu_group { struct list_head list; struct tegra_smmu *smmu; - const struct tegra_smmu_group_soc *soc; + const struct tegra_smmu_group_soc *group_soc; struct iommu_group *grp; unsigned int swgroup; }; @@ -870,7 +870,7 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev) static void tegra_smmu_release_device(struct device *dev) {} static const struct tegra_smmu_group_soc * -tegra_smmu_find_group(struct tegra_smmu *smmu, unsigned int swgroup) +tegra_smmu_find_group_soc(struct tegra_smmu *smmu, unsigned int swgroup) { unsigned int i, j; @@ -896,19 +896,20 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); struct tegra_smmu *smmu = dev_iommu_priv_get(dev); - const struct tegra_smmu_group_soc *soc; + const struct tegra_smmu_group_soc *group_soc; unsigned int swgroup = fwspec->ids[0]; struct tegra_smmu_group *group; struct iommu_group *grp; /* Find group_soc associating with swgroup */ - soc = tegra_smmu_find_group(smmu, swgroup); + group_soc = tegra_smmu_find_group_soc(smmu, swgroup); mutex_lock(&smmu->lock); /* Find existing iommu_group associating with swgroup or group_soc */ list_for_each_entry(group, &smmu->groups, list) - if ((group->swgroup == swgroup) || (soc && group->soc == soc)) { + if ((group->swgroup == swgroup) || + (group_soc && group->group_soc == group_soc)) { grp = iommu_group_ref_get(group->grp); mutex_unlock(&smmu->lock); return grp; @@ -921,9 +922,9 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) } INIT_LIST_HEAD(&group->list); + group->group_soc = group_soc; group->swgroup = swgroup; group->smmu = smmu; - group->soc = soc; if (dev_is_pci(dev)) group->grp = pci_device_group(dev); @@ -937,8 +938,8 @@ static struct iommu_group *tegra_smmu_device_group(struct device *dev) } iommu_group_set_iommudata(group->grp, group, tegra_smmu_group_release); - if (soc) - iommu_group_set_name(group->grp, soc->name); + if (group_soc) + iommu_group_set_name(group->grp, group_soc->name); list_add_tail(&group->list, &smmu->groups); mutex_unlock(&smmu->lock); -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 0/6] iommu/tegra-smmu: Add pagetable mappings to debugfs
This series of patches adds a new mappings node to debugfs for tegra-smmu driver. The first five patches are all preparational changes for PATCH-6, based on Thierry's review feedback against v5: https://lkml.org/lkml/2021/3/16/447 Changelog v6: * Added PATCH1-3 for better naming conventions * Added PATCH4-5 to embed previous struct tegra_smmu_group_debug into struct tegra_smmu_group * Dropped parentheses at SMMU_PTE_ATTR_SHIFT * Dropped swgrp->reg print * Replaced ptb_reg contents with as->attr and as->pd_dma * Added "index" and "count" in the PD entries for readability * Removed Dmitry's Tested-by and Reviewed-by for the big change from v5 to v6. v5: https://lkml.org/lkml/2021/3/15/2473 * Fixed a typo in commit message * Split a long line into two lines * Rearranged variable defines by length * Added Tested-by and Reviewed-by from Dmitry v4: https://lkml.org/lkml/2021/3/14/429 * Changed %d to %u for unsigned variables * Fixed print format mismatch warnings on ARM32 v3: https://lkml.org/lkml/2021/3/14/30 * Fixed PHYS and IOVA print formats * Changed variables to unsigned int type * Changed the table outputs to be compact v2: https://lkml.org/lkml/2021/3/9/1382 * Expanded mutex range to the entire function * Added as->lock to protect pagetable walkthrough * Replaced devm_kzalloc with devm_kcalloc for group_debug * Added "PTE RANGE" and "SIZE" columns to group contiguous mappings * Dropped as->count check * Added WARN_ON when as->count mismatches pd[pd_index] v1: https://lkml.org/lkml/2020/9/26/70 Nicolin Chen (6): iommu/tegra-smmu: Rename struct iommu_group *group to *grp iommu/tegra-smmu: Rename struct tegra_smmu_group_soc *soc to *group_soc iommu/tegra-smmu: Rename struct tegra_smmu_swgroup *group to *swgrp iommu/tegra-smmu: Use swgrp pointer instead of swgroup id iommu/tegra-smmu: Attach as pointer to tegra_smmu_group iommu/tegra-smmu: Add pagetable mappings to debugfs drivers/iommu/tegra-smmu.c | 312 +++-- 1 file changed, 262 insertions(+), 50 deletions(-) -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] dma-debug: prevent an error message from causing runtime problems
Thanks a lot. I've applied this with a little change to avoid breaking up the printed string into two lines. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/dma: Tidy up Kconfig selects
Now that the dust has settled on converting all the x86 drivers to iommu-dma, we can punt the Kconfig selection to arch code where it was always intended to be. CC: Christoph Hellwig CC: Marek Szyprowski CC: x...@kernel.org CC: linux-i...@vger.kernel.org Signed-off-by: Robin Murphy --- arch/ia64/Kconfig | 1 + arch/x86/Kconfig| 1 + drivers/iommu/Kconfig | 1 - drivers/iommu/amd/Kconfig | 1 - drivers/iommu/intel/Kconfig | 1 - 5 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 045792cde481..56c00a0851ce 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -51,6 +51,7 @@ config IA64 select GENERIC_TIME_VSYSCALL select LEGACY_TIMER_TICK select SWIOTLB + select IOMMU_DMA if INTEL_IOMMU select SYSCTL_ARCH_UNALIGN_NO_WARN select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4e001425..10ea941e7c80 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -247,6 +247,7 @@ config X86 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO select HOTPLUG_SMT if SMP + select IOMMU_DMAif IOMMU_SUPPORT select IRQ_FORCED_THREADING select NEED_SG_DMA_LENGTH select PCI_DOMAINS if PCI diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 124c41adeca1..3538a2f38b94 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -459,7 +459,6 @@ config VIRTIO_IOMMU depends on VIRTIO depends on (ARM64 || X86) select IOMMU_API - select IOMMU_DMA select INTERVAL_TREE select ACPI_VIOT if ACPI help diff --git a/drivers/iommu/amd/Kconfig b/drivers/iommu/amd/Kconfig index a3cbafb603f5..9b5fc3356bf2 100644 --- a/drivers/iommu/amd/Kconfig +++ b/drivers/iommu/amd/Kconfig @@ -9,7 +9,6 @@ config AMD_IOMMU select PCI_PASID select IOMMU_API select IOMMU_IOVA - select IOMMU_DMA select IOMMU_IO_PGTABLE depends on X86_64 && PCI && ACPI && HAVE_CMPXCHG_DOUBLE help diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig index 0ddb77115be7..28c3e922ca27 100644 --- a/drivers/iommu/intel/Kconfig +++ b/drivers/iommu/intel/Kconfig @@ -16,7 +16,6 @@ config INTEL_IOMMU select DMAR_TABLE select SWIOTLB select IOASID - select IOMMU_DMA select PCI_ATS help DMA remapping (DMAR) devices support enables independent address -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/2] iommu/dma: Unexport IOVA cookie management
IOVA cookies are now got and put by core code, so we no longer need to export these to modular drivers. The export for getting MSI cookies stays, since VFIO can still be a module, but it was already relying on someone else putting them, so that aspect is unaffected. Reviewed-by: Lu Baolu Reviewed-by: Jean-Philippe Brucker Signed-off-by: Robin Murphy --- drivers/iommu/dma-iommu.c | 7 --- drivers/iommu/iommu.c | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 896bea04c347..26cb95d3830a 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -98,9 +98,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type) /** * iommu_get_dma_cookie - Acquire DMA-API resources for a domain * @domain: IOMMU domain to prepare for DMA-API usage - * - * IOMMU drivers should normally call this from their domain_alloc - * callback when domain->type == IOMMU_DOMAIN_DMA. */ int iommu_get_dma_cookie(struct iommu_domain *domain) { @@ -113,7 +110,6 @@ int iommu_get_dma_cookie(struct iommu_domain *domain) return 0; } -EXPORT_SYMBOL(iommu_get_dma_cookie); /** * iommu_get_msi_cookie - Acquire just MSI remapping resources @@ -151,8 +147,6 @@ EXPORT_SYMBOL(iommu_get_msi_cookie); * iommu_put_dma_cookie - Release a domain's DMA mapping resources * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie() or * iommu_get_msi_cookie() - * - * IOMMU drivers should normally call this from their domain_free callback. */ void iommu_put_dma_cookie(struct iommu_domain *domain) { @@ -172,7 +166,6 @@ void iommu_put_dma_cookie(struct iommu_domain *domain) kfree(cookie); domain->iova_cookie = NULL; } -EXPORT_SYMBOL(iommu_put_dma_cookie); /** * iommu_dma_get_resv_regions - Reserved region driver helper diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3303d707bab4..a80f13867bed 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1953,8 +1953,7 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, /* Assume all sizes by default; the driver may override this later */ domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap; - /* Temporarily avoid -EEXIST while drivers still get their own cookies */ - if (iommu_is_dma_domain(domain) && !domain->iova_cookie && iommu_get_dma_cookie(domain)) { + if (iommu_is_dma_domain(domain) && iommu_get_dma_cookie(domain)) { iommu_domain_free(domain); domain = NULL; } -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/2] iommu/dart: Clean up IOVA cookie crumbs
The addition of the DART driver crossed over with moving IOVA cookie management into core code; clean up the now-unnecessary remnants here. Acked-by: Sven Peter Tested-by: Sven Peter Signed-off-by: Robin Murphy --- drivers/iommu/apple-dart.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index 559db9259e65..cdc2e83b2186 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -596,7 +595,6 @@ static struct iommu_domain *apple_dart_domain_alloc(unsigned int type) if (!dart_domain) return NULL; - iommu_get_dma_cookie(&dart_domain->domain); mutex_init(&dart_domain->init_lock); /* no need to allocate pgtbl_ops or do any other finalization steps */ -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/2] iommu: DMA domain epilogue
Hi Joerg, As planned, here are the follow-up patches to resolve the merge of the DART driver with the core changes. There's some argument for this being 5.15 fix material (the driver getting DMA cookies unconditionally is still technically wrong), but in practice it shouldn't be an issue either if you'd prefer to treat it as cleanup for 5.16. Your choice :) Cheers, Robin. Robin Murphy (2): iommu/dart: Clean up IOVA cookie crumbs iommu/dma: Unexport IOVA cookie management drivers/iommu/apple-dart.c | 2 -- drivers/iommu/dma-iommu.c | 7 --- drivers/iommu/iommu.c | 3 +-- 3 files changed, 1 insertion(+), 11 deletions(-) -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v7 0/7] Fixes for dma-iommu swiotlb bounce buffers
Is there further feedback on these patches? Only patch 7 is still pending review. -David On Mon, Aug 30, 2021 at 2:00 PM David Stevens wrote: > > This patch set includes various fixes for dma-iommu's swiotlb bounce > buffers for untrusted devices. > > The min_align_mask issue was found when running fio on an untrusted nvme > device with bs=512. The other issues were found via code inspection, so > I don't have any specific use cases where things were not working, nor > any concrete performance numbers. > > There are two issues related to min_align_mask that this patch series > does not attempt to fix. First, it does not address the case where > min_align_mask is larger than the IOVA granule. Doing so requires > changes to IOVA allocation, and is not specific to when swiotlb bounce > buffers are used. This is not a problem in practice today, since the > only driver which uses min_align_mask is nvme, which sets it to 4096. > > The second issue this series does not address is the fact that extra > swiotlb slots adjacent to a bounce buffer can be exposed to untrusted > devices whose drivers use min_align_mask. Fixing this requires being > able to allocate padding slots at the beginning of a swiotlb allocation. > This is a rather significant change that I am not comfortable making. > Without being able to handle this, there is also little point to > clearing the padding at the start of such a buffer, since we can only > clear based on (IO_TLB_SIZE - 1) instead of iova_mask. > > v6 -> v7: > - Remove unsafe attempt to clear padding at start of swiotlb buffer > - Rewrite commit message for min_align_mask commit to better explain >the problem it's fixing > - Rebase on iommu/core > - Acknowledge unsolved issues in cover letter > > v5 -> v6: > - Remove unnecessary line break > - Remove redundant config check > > v4 -> v5: > - Fix xen build error > - Move _swiotlb refactor into its own patch > > v3 -> v4: > - Fold _swiotlb functions into _page functions > - Add patch to align swiotlb buffer to iovad granule > - Combine if checks in iommu_dma_sync_sg_* functions > > v2 -> v3: > - Add new patch to address min_align_mask bug > - Set SKIP_CPU_SYNC flag after syncing in map/unmap > - Properly call arch_sync_dma_for_cpu in iommu_dma_sync_sg_for_cpu > > v1 -> v2: > - Split fixes into dedicated patches > - Less invasive changes to fix arch_sync when mapping > - Leave dev_is_untrusted check for strict iommu > > David Stevens (7): > dma-iommu: fix sync_sg with swiotlb > dma-iommu: fix arch_sync_dma for map > dma-iommu: skip extra sync during unmap w/swiotlb > dma-iommu: fold _swiotlb helpers into callers > dma-iommu: Check CONFIG_SWIOTLB more broadly > swiotlb: support aligned swiotlb buffers > dma-iommu: account for min_align_mask w/swiotlb > > drivers/iommu/dma-iommu.c | 188 +- > drivers/xen/swiotlb-xen.c | 2 +- > include/linux/swiotlb.h | 3 +- > kernel/dma/swiotlb.c | 11 ++- > 4 files changed, 93 insertions(+), 111 deletions(-) > > -- > 2.33.0.259.gc128427fd7-goog > ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu