[PATCH v2 3/3] iommu/vt-d: Fix ineffective devTLB invalidation for subdevices
iommu_flush_dev_iotlb() is called to invalidate caches on device. It only loops the devices which are full-attached to the domain. For sub-devices, this is ineffective. This results in invalid caching entries left on the device. Fix it by adding loop for subdevices as well. Also, the domain-> has_iotlb_device needs to be updated when attaching to subdevices. Fixes: 67b8e02b5e761 ("iommu/vt-d: Aux-domain specific domain attach/detach") Signed-off-by: Liu Yi L --- drivers/iommu/intel/iommu.c | 63 +++-- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index acfe0a5b955e..e97c5ac1d7fc 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -726,6 +726,8 @@ static int domain_update_device_node(struct dmar_domain *domain) return nid; } +static void domain_update_iotlb(struct dmar_domain *domain); + /* Some capabilities may be different across iommus */ static void domain_update_iommu_cap(struct dmar_domain *domain) { @@ -739,6 +741,8 @@ static void domain_update_iommu_cap(struct dmar_domain *domain) */ if (domain->nid == NUMA_NO_NODE) domain->nid = domain_update_device_node(domain); + + domain_update_iotlb(domain); } struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus, @@ -1459,6 +1463,18 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu, return NULL; } +static bool dev_iotlb_enabled(struct device_domain_info *info) +{ + struct pci_dev *pdev; + + if (!info->dev || !dev_is_pci(info->dev)) + return false; + + pdev = to_pci_dev(info->dev); + + return !!pdev->ats_enabled; +} + static void domain_update_iotlb(struct dmar_domain *domain) { struct device_domain_info *info; @@ -1466,17 +1482,20 @@ static void domain_update_iotlb(struct dmar_domain *domain) assert_spin_locked(_domain_lock); - list_for_each_entry(info, >devices, link) { - struct pci_dev *pdev; - - if (!info->dev || !dev_is_pci(info->dev)) - continue; - - pdev = to_pci_dev(info->dev); - if (pdev->ats_enabled) { + list_for_each_entry(info, >devices, link) + if (dev_iotlb_enabled(info)) { has_iotlb_device = true; break; } + + if (!has_iotlb_device) { + struct subdev_domain_info *sinfo; + + list_for_each_entry(sinfo, >subdevices, link_domain) + if (dev_iotlb_enabled(get_domain_info(sinfo->pdev))) { + has_iotlb_device = true; + break; + } } domain->has_iotlb_device = has_iotlb_device; @@ -1557,25 +1576,37 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info) #endif } +static void __iommu_flush_dev_iotlb(struct device_domain_info *info, + u64 addr, unsigned int mask) +{ + u16 sid, qdep; + + if (!info || !info->ats_enabled) + return; + + sid = info->bus << 8 | info->devfn; + qdep = info->ats_qdep; + qi_flush_dev_iotlb(info->iommu, sid, info->pfsid, + qdep, addr, mask); +} + static void iommu_flush_dev_iotlb(struct dmar_domain *domain, u64 addr, unsigned mask) { - u16 sid, qdep; unsigned long flags; struct device_domain_info *info; + struct subdev_domain_info *sinfo; if (!domain->has_iotlb_device) return; spin_lock_irqsave(_domain_lock, flags); - list_for_each_entry(info, >devices, link) { - if (!info->ats_enabled) - continue; + list_for_each_entry(info, >devices, link) + __iommu_flush_dev_iotlb(info, addr, mask); - sid = info->bus << 8 | info->devfn; - qdep = info->ats_qdep; - qi_flush_dev_iotlb(info->iommu, sid, info->pfsid, - qdep, addr, mask); + list_for_each_entry(sinfo, >subdevices, link_domain) { + __iommu_flush_dev_iotlb(get_domain_info(sinfo->pdev), + addr, mask); } spin_unlock_irqrestore(_domain_lock, flags); } -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 2/3] iommu/vt-d: Track device aux-attach with subdevice_domain_info
In the existing code, loop all devices attached to a domain does not include sub-devices attached via iommu_aux_attach_device(). This was found by when I'm working on the belwo patch, There is no device in the domain->devices list, thus unable to get the cap and ecap of iommu unit. But this domain actually has subdevice which is attached via aux-manner. But it is tracked by domain. This patch is going to fix it. https://lore.kernel.org/kvm/1599734733-6431-17-git-send-email-yi.l@intel.com/ And this fix goes beyond the patch above, such sub-device tracking is necessary for other cases. For example, flushing device_iotlb for a domain which has sub-devices attached by auxiliary manner. Co-developed-by: Xin Zeng Signed-off-by: Xin Zeng Signed-off-by: Liu Yi L --- drivers/iommu/intel/iommu.c | 95 +++-- include/linux/intel-iommu.h | 16 +-- 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index a49afa11673c..acfe0a5b955e 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1881,6 +1881,7 @@ static struct dmar_domain *alloc_domain(int flags) domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL; domain->has_iotlb_device = false; INIT_LIST_HEAD(>devices); + INIT_LIST_HEAD(>subdevices); return domain; } @@ -2632,7 +2633,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, info->iommu = iommu; info->pasid_table = NULL; info->auxd_enabled = 0; - INIT_LIST_HEAD(>auxiliary_domains); + INIT_LIST_HEAD(>subdevices); if (dev && dev_is_pci(dev)) { struct pci_dev *pdev = to_pci_dev(info->dev); @@ -5172,33 +5173,61 @@ is_aux_domain(struct device *dev, struct iommu_domain *domain) domain->type == IOMMU_DOMAIN_UNMANAGED; } -static void auxiliary_link_device(struct dmar_domain *domain, - struct device *dev) +static inline struct subdev_domain_info * +lookup_subdev_info(struct dmar_domain *domain, struct device *dev) +{ + struct subdev_domain_info *sinfo; + + if (!list_empty(>subdevices)) { + list_for_each_entry(sinfo, >subdevices, link_domain) { + if (sinfo->pdev == dev) + return sinfo; + } + } + + return NULL; +} + +static int auxiliary_link_device(struct dmar_domain *domain, +struct device *dev) { struct device_domain_info *info = get_domain_info(dev); + struct subdev_domain_info *sinfo = lookup_subdev_info(domain, dev); assert_spin_locked(_domain_lock); if (WARN_ON(!info)) - return; + return -EINVAL; + + if (!sinfo) { + sinfo = kzalloc(sizeof(*sinfo), GFP_ATOMIC); + sinfo->domain = domain; + sinfo->pdev = dev; + list_add(>link_phys, >subdevices); + list_add(>link_domain, >subdevices); + } - domain->auxd_refcnt++; - list_add(>auxd, >auxiliary_domains); + return ++sinfo->users; } -static void auxiliary_unlink_device(struct dmar_domain *domain, - struct device *dev) +static int auxiliary_unlink_device(struct dmar_domain *domain, + struct device *dev) { struct device_domain_info *info = get_domain_info(dev); + struct subdev_domain_info *sinfo = lookup_subdev_info(domain, dev); + int ret; assert_spin_locked(_domain_lock); - if (WARN_ON(!info)) - return; + if (WARN_ON(!info || !sinfo || sinfo->users <= 0)) + return -EINVAL; - list_del(>auxd); - domain->auxd_refcnt--; + ret = --sinfo->users; + if (!ret) { + list_del(>link_phys); + list_del(>link_domain); + kfree(sinfo); + } - if (!domain->auxd_refcnt && domain->default_pasid > 0) - ioasid_free(domain->default_pasid); + return ret; } static int aux_domain_add_dev(struct dmar_domain *domain, @@ -5227,6 +5256,19 @@ static int aux_domain_add_dev(struct dmar_domain *domain, } spin_lock_irqsave(_domain_lock, flags); + ret = auxiliary_link_device(domain, dev); + if (ret <= 0) + goto link_failed; + + /* +* Subdevices from the same physical device can be attached to the +* same domain. For such cases, only the first subdevice attachment +* needs to go through the full steps in this function. So if ret > +* 1, just goto out. +*/ + if (ret > 1) + goto out; + /* * iommu->lock must be held to attach domain to iommu and setup the * pasid entry for second level translation. @@ -5245,10
[PATCH v2 1/3] iommu/vt-d: Move intel_iommu info from struct intel_svm to struct intel_svm_dev
Current struct intel_svm has a field to record the struct intel_iommu pointer for a PASID bind. And struct intel_svm will be shared by all the devices bind to the same process. The devices may be behind different DMAR units. As the iommu driver code uses the intel_iommu pointer stored in intel_svm struct to do cache invalidations, it may only flush the cache on a single DMAR unit, for others, the cache invalidation is missed. As intel_svm struct already has a device list, this patch just moves the intel_iommu pointer to be a field of intel_svm_dev struct. Fixes: 1c4f88b7f1f92 ("iommu/vt-d: Shared virtual address in scalable mode") Cc: Lu Baolu Cc: Jacob Pan Cc: Raj Ashok Cc: David Woodhouse Reported-by: Guo Kaijie Reported-by: Xin Zeng Signed-off-by: Guo Kaijie Signed-off-by: Xin Zeng Signed-off-by: Liu Yi L Tested-by: Guo Kaijie --- drivers/iommu/intel/svm.c | 9 + include/linux/intel-iommu.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index 3242ebd0bca3..4a10c9ff368c 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -142,7 +142,7 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d } desc.qw2 = 0; desc.qw3 = 0; - qi_submit_sync(svm->iommu, , 1, 0); + qi_submit_sync(sdev->iommu, , 1, 0); if (sdev->dev_iotlb) { desc.qw0 = QI_DEV_EIOTLB_PASID(svm->pasid) | @@ -166,7 +166,7 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d } desc.qw2 = 0; desc.qw3 = 0; - qi_submit_sync(svm->iommu, , 1, 0); + qi_submit_sync(sdev->iommu, , 1, 0); } } @@ -211,7 +211,7 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) */ rcu_read_lock(); list_for_each_entry_rcu(sdev, >devs, list) - intel_pasid_tear_down_entry(svm->iommu, sdev->dev, + intel_pasid_tear_down_entry(sdev->iommu, sdev->dev, svm->pasid, true); rcu_read_unlock(); @@ -363,6 +363,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, } sdev->dev = dev; sdev->sid = PCI_DEVID(info->bus, info->devfn); + sdev->iommu = iommu; /* Only count users if device has aux domains */ if (iommu_dev_feature_enabled(dev, IOMMU_DEV_FEAT_AUX)) @@ -546,6 +547,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, goto out; } sdev->dev = dev; + sdev->iommu = iommu; ret = intel_iommu_enable_pasid(iommu, dev); if (ret) { @@ -575,7 +577,6 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, kfree(sdev); goto out; } - svm->iommu = iommu; if (pasid_max > intel_pasid_max_id) pasid_max = intel_pasid_max_id; diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index d956987ed032..94522685a0d9 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -758,6 +758,7 @@ struct intel_svm_dev { struct list_head list; struct rcu_head rcu; struct device *dev; + struct intel_iommu *iommu; struct svm_dev_ops *ops; struct iommu_sva sva; u32 pasid; @@ -771,7 +772,6 @@ struct intel_svm { struct mmu_notifier notifier; struct mm_struct *mm; - struct intel_iommu *iommu; unsigned int flags; u32 pasid; int gpasid; /* In case that guest PASID is different from host PASID */ -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 0/3] iommu/vt-d: Misc fixes on scalable mode
This patchset aims to fix a bug regards to native SVM usage, and also several bugs around subdevice (attached to device via auxiliary manner) tracking and ineffective device_tlb flush. Liu Yi L (3): iommu/vt-d: Move intel_iommu info from struct intel_svm to struct intel_svm_dev iommu/vt-d: Track device aux-attach with subdevice_domain_info iommu/vt-d: Fix ineffective devTLB invalidation for subdevices drivers/iommu/intel/iommu.c | 158 +++- drivers/iommu/intel/svm.c | 9 +- include/linux/intel-iommu.h | 18 ++-- 3 files changed, 135 insertions(+), 50 deletions(-) -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] x86/iommu: Fix two minimal issues in check_iommu_entries()
check_iommu_entries() checks for cyclic dependency in iommu entries and fixes the cyclic dependency by setting x->depend to NULL. But this repairing isn't correct if q is in front of p, there will be "EXECUTION ORDER INVALID!" report following. Fix it by NULLing whichever in the front. The second issue is about the report of exectuion order reverse, the order is reversed incorrectly in the report, fix it. Signed-off-by: Zhenzhong Duan --- arch/x86/kernel/pci-iommu_table.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c index 2e9006c..40c8249 100644 --- a/arch/x86/kernel/pci-iommu_table.c +++ b/arch/x86/kernel/pci-iommu_table.c @@ -60,7 +60,10 @@ void __init check_iommu_entries(struct iommu_table_entry *start, printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %pS depends on %pS and vice-versa. BREAKING IT.\n", p->detect, q->detect); /* Heavy handed way..*/ - x->depend = NULL; + if (p > q) + q->depend = NULL; + else + p->depend = NULL; } } @@ -68,7 +71,7 @@ void __init check_iommu_entries(struct iommu_table_entry *start, q = find_dependents_of(p, finish, p); if (q && q > p) { printk(KERN_ERR "EXECUTION ORDER INVALID! %pS should be called before %pS!\n", - p->detect, q->detect); + q->detect, p->detect); } } } -- 1.8.3.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [PATCH 2/3] iommu/vt-d: Track device aux-attach with subdevice_domain_info.
Hi Jacob, > From: Jacob Pan > Sent: Wednesday, December 23, 2020 4:21 AM > > Hi Yi, > > On Sun, 20 Dec 2020 08:03:51 +0800, Liu Yi L wrote: > > > In existing code, if wanting to loop all devices attached to a domain, > > current code can only loop the devices which are attached to the domain > > via normal manner. While for devices attached via auxiliary manner, this > > is subdevice, they are not tracked in the domain. This patch adds struct > How about "In the existing code, loop all devices attached to a domain does > not include sub-devices attached via iommu_aux_attach_device()." looks good. will refine accordingly. > > > subdevice_domain_info which is created per domain attachment via > auxiliary > > manner. So that such devices are also tracked in domain. > > > > This was found by when I'm working on the belwo patch, There is no device > > in domain->devices, thus unable to get the cap and ecap of iommu unit. But > > this domain actually has one sub-device which is attached via aux-manner. > > This patch fixes the issue. > > > > https://lore.kernel.org/kvm/1599734733-6431-17-git-send-email- > yi.l@intel.com/ > > > > But looks like, it doesn't affect me only. Such auxiliary track should be > > there for example if wanting to flush device_iotlb for a domain which has > > devices attached by auxiliray manner, then this fix is also necessary. > Perhaps: > This fix goes beyond the patch above, such sub-device tracking is > necessary for other cases. For example, flushing device_iotlb for a domain > which has sub-devices attached by auxiliary manner. yep. Baolu also suggested such refine. will tweak in next version. Regards, Yi Liu > > > This issue will also be fixed by another patch in this series with some > > additional changes based on the sudevice tracking framework introduced in > > this patch. > > > > Co-developed-by: Xin Zeng > > Signed-off-by: Xin Zeng > > Co-developed-by: Liu Yi L > > Signed-off-by: Liu Yi L > > Co-developed-by: Lu Baolu > > Signed-off-by: Lu Baolu > > --- > > drivers/iommu/intel/iommu.c | 92 -- > --- > > include/linux/intel-iommu.h | 11 - > > 2 files changed, 90 insertions(+), 13 deletions(-) > > > > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c > > index a49afa11673c..4274b4acc325 100644 > > --- a/drivers/iommu/intel/iommu.c > > +++ b/drivers/iommu/intel/iommu.c > > @@ -1881,6 +1881,7 @@ static struct dmar_domain *alloc_domain(int > flags) > > domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL; > > domain->has_iotlb_device = false; > > INIT_LIST_HEAD(>devices); > > + INIT_LIST_HEAD(>sub_devices); > > > > return domain; > > } > > @@ -5172,33 +5173,79 @@ is_aux_domain(struct device *dev, struct > > iommu_domain *domain) domain->type == > IOMMU_DOMAIN_UNMANAGED; > > } > > > > +static inline > > +void _auxiliary_link_device(struct dmar_domain *domain, > > + struct subdevice_domain_info *subinfo, > > + struct device *dev) > > +{ > > + subinfo->users++; > > +} > > + > why pass in more arguments than subinfo? the function name does not match > what it does, seems just refcount inc. > > > +static inline > > +int _auxiliary_unlink_device(struct dmar_domain *domain, > > +struct subdevice_domain_info *subinfo, > > +struct device *dev) > > +{ > > + subinfo->users--; > > + return subinfo->users; > ditto. why not just > return subinfo->users--; > > > +} > > + > > static void auxiliary_link_device(struct dmar_domain *domain, > > struct device *dev) > > { > > struct device_domain_info *info = get_domain_info(dev); > > + struct subdevice_domain_info *subinfo; > > > > assert_spin_locked(_domain_lock); > > if (WARN_ON(!info)) > > return; > > > > + subinfo = kzalloc(sizeof(*subinfo), GFP_ATOMIC); > > + if (!subinfo) > > + return; > > + > > + subinfo->domain = domain; > > + subinfo->dev = dev; > > + list_add(>link_domain, >auxiliary_domains); > > + list_add(>link_phys, >sub_devices); > > + _auxiliary_link_device(domain, subinfo, dev); > or just opencode subinfo->users++? > > domain->auxd_refcnt++; > > - list_add(>auxd, >auxiliary_domains); > > } > > > > -static void auxiliary_unlink_device(struct dmar_domain *domain, > > - struct device *dev) > > +static struct subdevice_domain_info * > > +subdevice_domain_info_lookup(struct dmar_domain *domain, struct > device > > *dev) +{ > > + struct subdevice_domain_info *subinfo; > > + > > + assert_spin_locked(_domain_lock); > > + > > + list_for_each_entry(subinfo, >sub_devices, link_phys) > > + if (subinfo->dev == dev) > > + return subinfo; > > + > > + return NULL; > > +} > > + > > +static int auxiliary_unlink_device(struct dmar_domain *domain, > > + struct
RE: [PATCH 0/4] iommu/vtd-: Misc fixes on scalable mode
> From: Jacob Pan > Sent: Wednesday, December 23, 2020 2:17 AM > > Hi Yi, > > nit: The cover letter is 0/4, patches are 1/3 - 3/3. You also need to copy > LKML. > > On Sun, 20 Dec 2020 08:03:49 +0800, Liu Yi L wrote: > > > Hi, > > > > This patchset aims to fix a bug regards to SVM usage on native, and > perhaps 'native SVM usage' got it. thanks. will correct it. Regards, Yi Liu > > also several bugs around subdevice (attached to device via auxiliary > > manner) tracking and ineffective device_tlb flush. > > > > Regards, > > Yi Liu > > > > Liu Yi L (3): > > iommu/vt-d: Move intel_iommu info from struct intel_svm to struct > > intel_svm_dev > > iommu/vt-d: Track device aux-attach with subdevice_domain_info. > > iommu/vt-d: A fix to iommu_flush_dev_iotlb() for aux-domain > > > > drivers/iommu/intel/iommu.c | 182 ++--- > --- > > drivers/iommu/intel/svm.c | 9 +- > > include/linux/intel-iommu.h | 13 ++- > > 3 files changed, 168 insertions(+), 36 deletions(-) > > > > > Thanks, > > Jacob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH AUTOSEL 4.4 26/38] iommu/tegra-smmu: Expand mutex protection range
From: Nicolin Chen [ Upstream commit d5f583bf8654c231b781096bc1a186065cda72b3 ] This is used to protect potential race condition at use_count. since probes of client drivers, calling attach_dev(), may run concurrently. Signed-off-by: Nicolin Chen Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20201125101013.14953-3-nicoleots...@gmail.com Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/tegra-smmu.c | 34 +- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 04cec050e42bf..ae796342717a6 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -241,26 +241,19 @@ static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp) { unsigned long id; - mutex_lock(>lock); - id = find_first_zero_bit(smmu->asids, smmu->soc->num_asids); - if (id >= smmu->soc->num_asids) { - mutex_unlock(>lock); + if (id >= smmu->soc->num_asids) return -ENOSPC; - } set_bit(id, smmu->asids); *idp = id; - mutex_unlock(>lock); return 0; } static void tegra_smmu_free_asid(struct tegra_smmu *smmu, unsigned int id) { - mutex_lock(>lock); clear_bit(id, smmu->asids); - mutex_unlock(>lock); } static bool tegra_smmu_capable(enum iommu_cap cap) @@ -395,17 +388,21 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { u32 value; - int err; + int err = 0; + + mutex_lock(>lock); if (as->use_count > 0) { as->use_count++; - return 0; + goto unlock; } as->pd_dma = dma_map_page(smmu->dev, as->pd, 0, SMMU_SIZE_PD, DMA_TO_DEVICE); - if (dma_mapping_error(smmu->dev, as->pd_dma)) - return -ENOMEM; + if (dma_mapping_error(smmu->dev, as->pd_dma)) { + err = -ENOMEM; + goto unlock; + } /* We can't handle 64-bit DMA addresses */ if (!smmu_dma_addr_valid(smmu, as->pd_dma)) { @@ -428,24 +425,35 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, as->smmu = smmu; as->use_count++; + mutex_unlock(>lock); + return 0; err_unmap: dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); +unlock: + mutex_unlock(>lock); + return err; } static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { - if (--as->use_count > 0) + mutex_lock(>lock); + + if (--as->use_count > 0) { + mutex_unlock(>lock); return; + } tegra_smmu_free_asid(smmu, as->id); dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); as->smmu = NULL; + + mutex_unlock(>lock); } static int tegra_smmu_attach_dev(struct iommu_domain *domain, -- 2.27.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH AUTOSEL 4.9 31/48] iommu/tegra-smmu: Expand mutex protection range
From: Nicolin Chen [ Upstream commit d5f583bf8654c231b781096bc1a186065cda72b3 ] This is used to protect potential race condition at use_count. since probes of client drivers, calling attach_dev(), may run concurrently. Signed-off-by: Nicolin Chen Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20201125101013.14953-3-nicoleots...@gmail.com Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/tegra-smmu.c | 34 +- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 04cec050e42bf..ae796342717a6 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -241,26 +241,19 @@ static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp) { unsigned long id; - mutex_lock(>lock); - id = find_first_zero_bit(smmu->asids, smmu->soc->num_asids); - if (id >= smmu->soc->num_asids) { - mutex_unlock(>lock); + if (id >= smmu->soc->num_asids) return -ENOSPC; - } set_bit(id, smmu->asids); *idp = id; - mutex_unlock(>lock); return 0; } static void tegra_smmu_free_asid(struct tegra_smmu *smmu, unsigned int id) { - mutex_lock(>lock); clear_bit(id, smmu->asids); - mutex_unlock(>lock); } static bool tegra_smmu_capable(enum iommu_cap cap) @@ -395,17 +388,21 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { u32 value; - int err; + int err = 0; + + mutex_lock(>lock); if (as->use_count > 0) { as->use_count++; - return 0; + goto unlock; } as->pd_dma = dma_map_page(smmu->dev, as->pd, 0, SMMU_SIZE_PD, DMA_TO_DEVICE); - if (dma_mapping_error(smmu->dev, as->pd_dma)) - return -ENOMEM; + if (dma_mapping_error(smmu->dev, as->pd_dma)) { + err = -ENOMEM; + goto unlock; + } /* We can't handle 64-bit DMA addresses */ if (!smmu_dma_addr_valid(smmu, as->pd_dma)) { @@ -428,24 +425,35 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, as->smmu = smmu; as->use_count++; + mutex_unlock(>lock); + return 0; err_unmap: dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); +unlock: + mutex_unlock(>lock); + return err; } static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { - if (--as->use_count > 0) + mutex_lock(>lock); + + if (--as->use_count > 0) { + mutex_unlock(>lock); return; + } tegra_smmu_free_asid(smmu, as->id); dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); as->smmu = NULL; + + mutex_unlock(>lock); } static int tegra_smmu_attach_dev(struct iommu_domain *domain, -- 2.27.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH AUTOSEL 4.14 41/66] iommu/tegra-smmu: Expand mutex protection range
From: Nicolin Chen [ Upstream commit d5f583bf8654c231b781096bc1a186065cda72b3 ] This is used to protect potential race condition at use_count. since probes of client drivers, calling attach_dev(), may run concurrently. Signed-off-by: Nicolin Chen Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20201125101013.14953-3-nicoleots...@gmail.com Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/tegra-smmu.c | 34 +- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 848dac3e4580f..30f0c72d685fe 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -244,26 +244,19 @@ static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp) { unsigned long id; - mutex_lock(>lock); - id = find_first_zero_bit(smmu->asids, smmu->soc->num_asids); - if (id >= smmu->soc->num_asids) { - mutex_unlock(>lock); + if (id >= smmu->soc->num_asids) return -ENOSPC; - } set_bit(id, smmu->asids); *idp = id; - mutex_unlock(>lock); return 0; } static void tegra_smmu_free_asid(struct tegra_smmu *smmu, unsigned int id) { - mutex_lock(>lock); clear_bit(id, smmu->asids); - mutex_unlock(>lock); } static bool tegra_smmu_capable(enum iommu_cap cap) @@ -398,17 +391,21 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { u32 value; - int err; + int err = 0; + + mutex_lock(>lock); if (as->use_count > 0) { as->use_count++; - return 0; + goto unlock; } as->pd_dma = dma_map_page(smmu->dev, as->pd, 0, SMMU_SIZE_PD, DMA_TO_DEVICE); - if (dma_mapping_error(smmu->dev, as->pd_dma)) - return -ENOMEM; + if (dma_mapping_error(smmu->dev, as->pd_dma)) { + err = -ENOMEM; + goto unlock; + } /* We can't handle 64-bit DMA addresses */ if (!smmu_dma_addr_valid(smmu, as->pd_dma)) { @@ -431,24 +428,35 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, as->smmu = smmu; as->use_count++; + mutex_unlock(>lock); + return 0; err_unmap: dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); +unlock: + mutex_unlock(>lock); + return err; } static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { - if (--as->use_count > 0) + mutex_lock(>lock); + + if (--as->use_count > 0) { + mutex_unlock(>lock); return; + } tegra_smmu_free_asid(smmu, as->id); dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); as->smmu = NULL; + + mutex_unlock(>lock); } static int tegra_smmu_attach_dev(struct iommu_domain *domain, -- 2.27.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH AUTOSEL 4.19 49/87] iommu/tegra-smmu: Expand mutex protection range
From: Nicolin Chen [ Upstream commit d5f583bf8654c231b781096bc1a186065cda72b3 ] This is used to protect potential race condition at use_count. since probes of client drivers, calling attach_dev(), may run concurrently. Signed-off-by: Nicolin Chen Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20201125101013.14953-3-nicoleots...@gmail.com Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/tegra-smmu.c | 34 +- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index fa0ecb5e63809..63679cce95054 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -252,26 +252,19 @@ static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp) { unsigned long id; - mutex_lock(>lock); - id = find_first_zero_bit(smmu->asids, smmu->soc->num_asids); - if (id >= smmu->soc->num_asids) { - mutex_unlock(>lock); + if (id >= smmu->soc->num_asids) return -ENOSPC; - } set_bit(id, smmu->asids); *idp = id; - mutex_unlock(>lock); return 0; } static void tegra_smmu_free_asid(struct tegra_smmu *smmu, unsigned int id) { - mutex_lock(>lock); clear_bit(id, smmu->asids); - mutex_unlock(>lock); } static bool tegra_smmu_capable(enum iommu_cap cap) @@ -406,17 +399,21 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { u32 value; - int err; + int err = 0; + + mutex_lock(>lock); if (as->use_count > 0) { as->use_count++; - return 0; + goto unlock; } as->pd_dma = dma_map_page(smmu->dev, as->pd, 0, SMMU_SIZE_PD, DMA_TO_DEVICE); - if (dma_mapping_error(smmu->dev, as->pd_dma)) - return -ENOMEM; + if (dma_mapping_error(smmu->dev, as->pd_dma)) { + err = -ENOMEM; + goto unlock; + } /* We can't handle 64-bit DMA addresses */ if (!smmu_dma_addr_valid(smmu, as->pd_dma)) { @@ -439,24 +436,35 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, as->smmu = smmu; as->use_count++; + mutex_unlock(>lock); + return 0; err_unmap: dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); +unlock: + mutex_unlock(>lock); + return err; } static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { - if (--as->use_count > 0) + mutex_lock(>lock); + + if (--as->use_count > 0) { + mutex_unlock(>lock); return; + } tegra_smmu_free_asid(smmu, as->id); dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); as->smmu = NULL; + + mutex_unlock(>lock); } static int tegra_smmu_attach_dev(struct iommu_domain *domain, -- 2.27.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH AUTOSEL 5.4 128/130] x86, swiotlb: Adjust SWIOTLB bounce buffer size for SEV guests
From: Ashish Kalra [ Upstream commit e998879d4fb7991856916972168cf27c0d86ed12 ] For SEV, all DMA to and from guest has to use shared (un-encrypted) pages. SEV uses SWIOTLB to make this happen without requiring changes to device drivers. However, depending on the workload being run, the default 64MB of it might not be enough and it may run out of buffers to use for DMA, resulting in I/O errors and/or performance degradation for high I/O workloads. Adjust the default size of SWIOTLB for SEV guests using a percentage of the total memory available to guest for the SWIOTLB buffers. Adds a new sev_setup_arch() function which is invoked from setup_arch() and it calls into a new swiotlb generic code function swiotlb_adjust_size() to do the SWIOTLB buffer adjustment. v5 fixed build errors and warnings as Reported-by: kbuild test robot Signed-off-by: Ashish Kalra Co-developed-by: Borislav Petkov Signed-off-by: Borislav Petkov Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Sasha Levin --- arch/x86/include/asm/mem_encrypt.h | 2 ++ arch/x86/kernel/setup.c| 6 ++ arch/x86/mm/mem_encrypt.c | 31 ++ include/linux/swiotlb.h| 8 kernel/dma/swiotlb.c | 20 +-- 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h index 848ce43b9040d..6c36956452ca6 100644 --- a/arch/x86/include/asm/mem_encrypt.h +++ b/arch/x86/include/asm/mem_encrypt.h @@ -36,6 +36,7 @@ void __init sme_map_bootdata(char *real_mode_data); void __init sme_unmap_bootdata(char *real_mode_data); void __init sme_early_init(void); +void __init sev_setup_arch(void); void __init sme_encrypt_kernel(struct boot_params *bp); void __init sme_enable(struct boot_params *bp); @@ -65,6 +66,7 @@ static inline void __init sme_map_bootdata(char *real_mode_data) { } static inline void __init sme_unmap_bootdata(char *real_mode_data) { } static inline void __init sme_early_init(void) { } +static inline void __init sev_setup_arch(void) { } static inline void __init sme_encrypt_kernel(struct boot_params *bp) { } static inline void __init sme_enable(struct boot_params *bp) { } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 77ea96b794bd1..9dc0c94e1544f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1120,6 +1120,12 @@ void __init setup_arch(char **cmdline_p) memblock_set_current_limit(ISA_END_ADDRESS); e820__memblock_setup(); + /* +* Needs to run after memblock setup because it needs the physical +* memory size. +*/ + sev_setup_arch(); + reserve_bios_regions(); if (efi_enabled(EFI_MEMMAP)) { diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 9268c12458c84..5911cfa31bc6d 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -196,6 +196,37 @@ void __init sme_early_init(void) swiotlb_force = SWIOTLB_FORCE; } +void __init sev_setup_arch(void) +{ + phys_addr_t total_mem = memblock_phys_mem_size(); + unsigned long size; + + if (!sev_active()) + return; + + /* +* For SEV, all DMA has to occur via shared/unencrypted pages. +* SEV uses SWIOTLB to make this happen without changing device +* drivers. However, depending on the workload being run, the +* default 64MB of SWIOTLB may not be enough and SWIOTLB may +* run out of buffers for DMA, resulting in I/O errors and/or +* performance degradation especially with high I/O workloads. +* +* Adjust the default size of SWIOTLB for SEV guests using +* a percentage of guest memory for SWIOTLB buffers. +* Also, as the SWIOTLB bounce buffer memory is allocated +* from low memory, ensure that the adjusted size is within +* the limits of low available memory. +* +* The percentage of guest memory used here for SWIOTLB buffers +* is more of an approximation of the static adjustment which +* 64MB for <1G, and ~128M to 256M for 1G-to-4G, i.e., the 6% +*/ + size = total_mem * 6 / 100; + size = clamp_val(size, IO_TLB_DEFAULT_SIZE, SZ_1G); + swiotlb_adjust_size(size); +} + static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc) { pgprot_t old_prot, new_prot; diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 0a8fced6aaec4..522a0942114ad 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -30,6 +30,9 @@ enum swiotlb_force { */ #define IO_TLB_SHIFT 11 +/* default to 64MB */ +#define IO_TLB_DEFAULT_SIZE (64UL<<20) + extern void swiotlb_init(int verbose); int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); extern unsigned long swiotlb_nr_tbl(void); @@ -80,6 +83,7 @@ void __init
[PATCH AUTOSEL 5.4 070/130] iommu/tegra-smmu: Expand mutex protection range
From: Nicolin Chen [ Upstream commit d5f583bf8654c231b781096bc1a186065cda72b3 ] This is used to protect potential race condition at use_count. since probes of client drivers, calling attach_dev(), may run concurrently. Signed-off-by: Nicolin Chen Tested-by: Dmitry Osipenko Reviewed-by: Dmitry Osipenko Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20201125101013.14953-3-nicoleots...@gmail.com Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/tegra-smmu.c | 34 +- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index dd486233e2828..41be3e2202971 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -247,26 +247,19 @@ static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp) { unsigned long id; - mutex_lock(>lock); - id = find_first_zero_bit(smmu->asids, smmu->soc->num_asids); - if (id >= smmu->soc->num_asids) { - mutex_unlock(>lock); + if (id >= smmu->soc->num_asids) return -ENOSPC; - } set_bit(id, smmu->asids); *idp = id; - mutex_unlock(>lock); return 0; } static void tegra_smmu_free_asid(struct tegra_smmu *smmu, unsigned int id) { - mutex_lock(>lock); clear_bit(id, smmu->asids); - mutex_unlock(>lock); } static bool tegra_smmu_capable(enum iommu_cap cap) @@ -404,17 +397,21 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { u32 value; - int err; + int err = 0; + + mutex_lock(>lock); if (as->use_count > 0) { as->use_count++; - return 0; + goto unlock; } as->pd_dma = dma_map_page(smmu->dev, as->pd, 0, SMMU_SIZE_PD, DMA_TO_DEVICE); - if (dma_mapping_error(smmu->dev, as->pd_dma)) - return -ENOMEM; + if (dma_mapping_error(smmu->dev, as->pd_dma)) { + err = -ENOMEM; + goto unlock; + } /* We can't handle 64-bit DMA addresses */ if (!smmu_dma_addr_valid(smmu, as->pd_dma)) { @@ -437,24 +434,35 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu, as->smmu = smmu; as->use_count++; + mutex_unlock(>lock); + return 0; err_unmap: dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); +unlock: + mutex_unlock(>lock); + return err; } static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, struct tegra_smmu_as *as) { - if (--as->use_count > 0) + mutex_lock(>lock); + + if (--as->use_count > 0) { + mutex_unlock(>lock); return; + } tegra_smmu_free_asid(smmu, as->id); dma_unmap_page(smmu->dev, as->pd_dma, SMMU_SIZE_PD, DMA_TO_DEVICE); as->smmu = NULL; + + mutex_unlock(>lock); } static int tegra_smmu_attach_dev(struct iommu_domain *domain, -- 2.27.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH AUTOSEL 5.10 065/217] pinctrl: qcom: Kconfig: Rework PINCTRL_MSM to be a depenency rather then a selected config
From: John Stultz [ Upstream commit be117ca32261c3331b614f440c737650791a6998 ] This patch reworks PINCTRL_MSM to be a visible option, and instead of having the various SoC specific drivers select PINCTRL_MSM, this switches those configs to depend on PINCTRL_MSM. This is useful, as it will be needed in order to cleanly support having the qcom-scm driver, which pinctrl-msm calls into, configured as a module. Without this change, we would eventually have to add dependency lines to every config that selects PINCTRL_MSM, and that would becomes a maintenance headache. We also add PINCTRL_MSM to the arm64 defconfig to avoid surprises as otherwise PINCTRL_MSM/IPQ* options previously enabled, will be off. Signed-off-by: John Stultz Reviewed-by: Bjorn Andersson Cc: Catalin Marinas Cc: Will Deacon Cc: Andy Gross Cc: Bjorn Andersson Cc: Joerg Roedel Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier Cc: Linus Walleij Cc: Vinod Koul Cc: Kalle Valo Cc: Maulik Shah Cc: Lina Iyer Cc: Saravana Kannan Cc: Todd Kjos Cc: Greg Kroah-Hartman Cc: linux-arm-...@vger.kernel.org Cc: iommu@lists.linux-foundation.org Cc: linux-g...@vger.kernel.org Link: https://lore.kernel.org/r/20201106042710.55979-1-john.stu...@linaro.org Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- arch/arm64/configs/defconfig | 1 + drivers/pinctrl/qcom/Kconfig | 48 ++-- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 5cfe3cf6f2acb..2ac53d8ae76a3 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -483,6 +483,7 @@ CONFIG_PINCTRL_IMX8MP=y CONFIG_PINCTRL_IMX8MQ=y CONFIG_PINCTRL_IMX8QXP=y CONFIG_PINCTRL_IMX8DXL=y +CONFIG_PINCTRL_MSM=y CONFIG_PINCTRL_IPQ8074=y CONFIG_PINCTRL_IPQ6018=y CONFIG_PINCTRL_MSM8916=y diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 5fe7b8aaf69d8..c9bb2d9e49d47 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -2,7 +2,7 @@ if (ARCH_QCOM || COMPILE_TEST) config PINCTRL_MSM - bool + bool "Qualcomm core pin controller driver" select PINMUX select PINCONF select GENERIC_PINCONF @@ -13,7 +13,7 @@ config PINCTRL_MSM config PINCTRL_APQ8064 tristate "Qualcomm APQ8064 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found in the Qualcomm APQ8064 platform. @@ -21,7 +21,7 @@ config PINCTRL_APQ8064 config PINCTRL_APQ8084 tristate "Qualcomm APQ8084 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found in the Qualcomm APQ8084 platform. @@ -29,7 +29,7 @@ config PINCTRL_APQ8084 config PINCTRL_IPQ4019 tristate "Qualcomm IPQ4019 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found in the Qualcomm IPQ4019 platform. @@ -37,7 +37,7 @@ config PINCTRL_IPQ4019 config PINCTRL_IPQ8064 tristate "Qualcomm IPQ8064 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found in the Qualcomm IPQ8064 platform. @@ -45,7 +45,7 @@ config PINCTRL_IPQ8064 config PINCTRL_IPQ8074 tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm Technologies Inc. TLMM block found on the @@ -55,7 +55,7 @@ config PINCTRL_IPQ8074 config PINCTRL_IPQ6018 tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm Technologies Inc. TLMM block found on the @@ -65,7 +65,7 @@ config PINCTRL_IPQ6018 config PINCTRL_MSM8226 tristate "Qualcomm 8226 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm Technologies Inc TLMM block found on the Qualcomm @@ -74,7 +74,7 @@ config PINCTRL_MSM8226 config PINCTRL_MSM8660 tristate "Qualcomm 8660 pin controller driver"
[PATCH v3 1/3] iommu/vt-d: Audit IOMMU Capabilities and add helper functions
Audit IOMMU Capability/Extended Capability and check if the IOMMUs have the consistent value for features. Report out or scale to the lowest supported when IOMMU features have incompatibility among IOMMUs. Report out features when below features are mismatched: - First Level 5 Level Paging Support (FL5LP) - First Level 1 GByte Page Support (FL1GP) - Read Draining (DRD) - Write Draining (DWD) - Page Selective Invalidation (PSI) - Zero Length Read (ZLR) - Caching Mode (CM) - Protected High/Low-Memory Region (PHMR/PLMR) - Required Write-Buffer Flushing (RWBF) - Advanced Fault Logging (AFL) - RID-PASID Support (RPS) - Scalable Mode Page Walk Coherency (SMPWC) - First Level Translation Support (FLTS) - Second Level Translation Support (SLTS) - No Write Flag Support (NWFS) - Second Level Accessed/Dirty Support (SLADS) - Virtual Command Support (VCS) - Scalable Mode Translation Support (SMTS) - Device TLB Invalidation Throttle (DIT) - Page Drain Support (PDS) - Process Address Space ID Support (PASID) - Extended Accessed Flag Support (EAFS) - Supervisor Request Support (SRS) - Execute Request Support (ERS) - Page Request Support (PRS) - Nested Translation Support (NEST) - Snoop Control (SC) - Pass Through (PT) - Device TLB Support (DT) - Queued Invalidation (QI) - Page walk Coherency (C) Set capability to the lowest supported when below features are mismatched: - Maximum Address Mask Value (MAMV) - Number of Fault Recording Registers (NFR) - Second Level Large Page Support (SLLPS) - Fault Recording Offset (FRO) - Maximum Guest Address Width (MGAW) - Supported Adjusted Guest Address Width (SAGAW) - Number of Domains supported (NDOMS) - Pasid Size Supported (PSS) - Maximum Handle Mask Value (MHMV) - IOTLB Register Offset (IRO) Signed-off-by: Kyung Min Park --- drivers/iommu/intel/Makefile| 2 +- drivers/iommu/intel/cap_audit.c | 188 drivers/iommu/intel/cap_audit.h | 106 drivers/iommu/intel/iommu.c | 9 ++ drivers/iommu/intel/irq_remapping.c | 8 ++ include/linux/intel-iommu.h | 39 +++--- 6 files changed, 333 insertions(+), 19 deletions(-) create mode 100644 drivers/iommu/intel/cap_audit.c create mode 100644 drivers/iommu/intel/cap_audit.h diff --git a/drivers/iommu/intel/Makefile b/drivers/iommu/intel/Makefile index fb8e1e8c8029..e3576a62612b 100644 --- a/drivers/iommu/intel/Makefile +++ b/drivers/iommu/intel/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DMAR_TABLE) += dmar.o obj-$(CONFIG_INTEL_IOMMU) += iommu.o pasid.o -obj-$(CONFIG_INTEL_IOMMU) += trace.o +obj-$(CONFIG_INTEL_IOMMU) += trace.o cap_audit.o obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += debugfs.o obj-$(CONFIG_INTEL_IOMMU_SVM) += svm.o obj-$(CONFIG_IRQ_REMAP) += irq_remapping.o diff --git a/drivers/iommu/intel/cap_audit.c b/drivers/iommu/intel/cap_audit.c new file mode 100644 index ..4a062fc719d2 --- /dev/null +++ b/drivers/iommu/intel/cap_audit.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * cap_audit.c - audit iommu capabilities for boot time and hot plug + * + * Copyright (C) 2020 Intel Corporation + * + * Author: Kyung Min Park + * Lu Baolu + */ + +#define pr_fmt(fmt)"DMAR: " fmt + +#include +#include "cap_audit.h" + +static u64 intel_iommu_cap_sanity; +static u64 intel_iommu_ecap_sanity; + +static inline void check_irq_capabilities(struct intel_iommu *a, + struct intel_iommu *b) +{ + CHECK_FEATURE_MISMATCH(a, b, cap, pi_support, CAP_PI_MASK); + CHECK_FEATURE_MISMATCH(a, b, ecap, eim_support, ECAP_EIM_MASK); +} + +static inline void check_dmar_capabilities(struct intel_iommu *a, + struct intel_iommu *b) +{ + MINIMAL_FEATURE_IOMMU(b, cap, CAP_MAMV_MASK); + MINIMAL_FEATURE_IOMMU(b, cap, CAP_NFR_MASK); + MINIMAL_FEATURE_IOMMU(b, cap, CAP_SLLPS_MASK); + MINIMAL_FEATURE_IOMMU(b, cap, CAP_FRO_MASK); + MINIMAL_FEATURE_IOMMU(b, cap, CAP_MGAW_MASK); + MINIMAL_FEATURE_IOMMU(b, cap, CAP_SAGAW_MASK); + MINIMAL_FEATURE_IOMMU(b, cap, CAP_NDOMS_MASK); + MINIMAL_FEATURE_IOMMU(b, ecap, ECAP_PSS_MASK); + MINIMAL_FEATURE_IOMMU(b, ecap, ECAP_MHMV_MASK); + MINIMAL_FEATURE_IOMMU(b, ecap, ECAP_IRO_MASK); + + CHECK_FEATURE_MISMATCH(a, b, cap, 5lp_support, CAP_FL5LP_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, fl1gp_support, CAP_FL1GP_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, read_drain, CAP_RD_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, write_drain, CAP_WD_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, pgsel_inv, CAP_PSI_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, zlr, CAP_ZLR_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, caching_mode, CAP_CM_MASK); + CHECK_FEATURE_MISMATCH(a, b, cap, phmr, CAP_PHMR_MASK); + CHECK_FEATURE_MISMATCH(a,
[PATCH v3 0/3] Audit Capability and Extended Capability among IOMMUs
Modern platforms have more than one IOMMU. Each IOMMU has its own feature set. Some of these features must be consistent among IOMMUs. Otherwise, these differences can lead to improper behavior in the system. On the other hand, for some features, each IOMMU can have different capacity values. So, different actions are required to deal with the inconsistencies depending on the IOMMU features. Currently, some inconsistencies are ignored by the IOMMU driver. This patchset checks IOMMU capabilities and extended capabilities centralizedly during boot and take different actions according to the impacts caused by the mismatches. For example: 1. Disable Shared Virtual Memory. 2. Use common capacity values (normally the lowest capacity value) for all IOMMUs. 3. Report feature mismatches. Detailed information on the IOMMU Capability / Extended Capability can be found in Intel VT-d Specification. Link: https://software.intel.com/sites/default/files/managed/c5/15/vt-directed-io-spec.pdf ChangeLog: - Change from v2 to v3: 1. fix the wrong macro names and rebase to v5.10. - Change from v1 to v2: 1. Add missing cap/ecaps for audit. 2. Refactor function/macros overal suggested by Lu, Baolu. 2. Skip audit for gfx dedicated IOMMU. 3. Change commit message. Kyung Min Park (3): iommu/vt-d: Audit IOMMU Capabilities and add helper functions iommu/vt-d: Move capability check code to cap_audit files iommu/vt-d: Disable SVM in the platform when IOMMUs have inconsistencies drivers/iommu/intel/Makefile| 2 +- drivers/iommu/intel/cap_audit.c | 219 drivers/iommu/intel/cap_audit.h | 132 + drivers/iommu/intel/iommu.c | 85 ++- drivers/iommu/intel/irq_remapping.c | 8 + drivers/iommu/intel/svm.c | 3 +- include/linux/intel-iommu.h | 39 ++--- 7 files changed, 394 insertions(+), 94 deletions(-) create mode 100644 drivers/iommu/intel/cap_audit.c create mode 100644 drivers/iommu/intel/cap_audit.h -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 3/3] iommu/vt-d: Disable SVM in the platform when IOMMUs have inconsistencies
Some IOMMU Capabilities must be consistent for Shared Virtual Memory (SVM). Audit IOMMU Capability/Extended Capabilities and check if IOMMUs have the consistent value for features as below. When the features are not matched among IOMMUs, disable SVMs in the platform during DMAR initialization. Audit IOMMUs again when a device is hot plugged. Disable Shared Virtual Memory when below features are mistmatched: - First Level Translation Support (FLTS) - Process Address Space ID Support (PASID) - Extended Accessed Flag Support (EAFS) - Supervisor Support (SRS) - Execute Request Support (ERS) - Page Request Support (PRS) Signed-off-by: Kyung Min Park --- drivers/iommu/intel/cap_audit.c | 11 +++ drivers/iommu/intel/cap_audit.h | 6 ++ drivers/iommu/intel/svm.c | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel/cap_audit.c b/drivers/iommu/intel/cap_audit.c index cf5326eb1d72..e6f8616edc3d 100644 --- a/drivers/iommu/intel/cap_audit.c +++ b/drivers/iommu/intel/cap_audit.c @@ -130,6 +130,12 @@ static int cap_audit_hotplug(struct intel_iommu *iommu, enum cap_audit_type type MINIMAL_FEATURE_HOTPLUG(iommu, ecap, max_handle_mask, ECAP_MHMV_MASK, mismatch); MINIMAL_FEATURE_HOTPLUG(iommu, ecap, iotlb_offset, ECAP_IRO_MASK, mismatch); + if (IS_ENABLED(CONFIG_INTEL_IOMMU_SVM) && + intel_cap_svm_santiy() && !ecap_svm_sanity(iommu->ecap)) { + pr_warn("Abort Hot Plug IOMMU: SVM inconsistent\n"); + mismatch = true; + } + out: if (mismatch) { intel_iommu_cap_sanity = old_cap; @@ -206,3 +212,8 @@ bool intel_cap_flts_sanity(void) { return ecap_flts(intel_iommu_ecap_sanity); } + +bool intel_cap_svm_santiy(void) +{ + return ecap_svm_sanity(intel_iommu_ecap_sanity); +} diff --git a/drivers/iommu/intel/cap_audit.h b/drivers/iommu/intel/cap_audit.h index 1ce1dc314950..beb2589e97e0 100644 --- a/drivers/iommu/intel/cap_audit.h +++ b/drivers/iommu/intel/cap_audit.h @@ -60,6 +60,11 @@ #define ECAP_QI_MASK BIT_ULL(1) #define ECAP_C_MASKBIT_ULL(0) +#define MINIMAL_SVM_ECAP (ECAP_FLTS_MASK | ECAP_PASID_MASK | ECAP_EAFS_MASK | \ + ECAP_SRS_MASK | ECAP_ERS_MASK | ECAP_PRS_MASK) + +#define ecap_svm_sanity(e) (!(((e) & MINIMAL_SVM_ECAP) ^ MINIMAL_SVM_ECAP)) + #define DO_CHECK_FEATURE_MISMATCH(a, b, cap, feature, MASK) \ do { \ if (cap##_##feature(a) != cap##_##feature(b)) { \ @@ -107,6 +112,7 @@ bool intel_cap_smts_sanity(void); bool intel_cap_pasid_sanity(void); bool intel_cap_nest_sanity(void); bool intel_cap_flts_sanity(void); +bool intel_cap_svm_santiy(void); static inline bool scalable_mode_support(void) { diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index f1861fa3d0e4..8a116c43f219 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -22,6 +22,7 @@ #include #include "pasid.h" +#include "cap_audit.h" static irqreturn_t prq_event_thread(int irq, void *d); static void intel_svm_drain_prq(struct device *dev, u32 pasid); @@ -98,7 +99,7 @@ static inline bool intel_svm_capable(struct intel_iommu *iommu) void intel_svm_check(struct intel_iommu *iommu) { - if (!pasid_supported(iommu)) + if (!intel_cap_svm_santiy()) return; if (cpu_feature_enabled(X86_FEATURE_GBPAGES) && -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 2/3] iommu/vt-d: Move capability check code to cap_audit files
Move IOMMU capability check and sanity check code to cap_audit files. Also implement some helper functions for sanity checks. Signed-off-by: Kyung Min Park --- drivers/iommu/intel/cap_audit.c | 20 + drivers/iommu/intel/cap_audit.h | 20 + drivers/iommu/intel/iommu.c | 76 + 3 files changed, 42 insertions(+), 74 deletions(-) diff --git a/drivers/iommu/intel/cap_audit.c b/drivers/iommu/intel/cap_audit.c index 4a062fc719d2..cf5326eb1d72 100644 --- a/drivers/iommu/intel/cap_audit.c +++ b/drivers/iommu/intel/cap_audit.c @@ -186,3 +186,23 @@ int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu) return -EFAULT; } + +bool intel_cap_smts_sanity(void) +{ + return ecap_smts(intel_iommu_ecap_sanity); +} + +bool intel_cap_pasid_sanity(void) +{ + return ecap_pasid(intel_iommu_ecap_sanity); +} + +bool intel_cap_nest_sanity(void) +{ + return ecap_nest(intel_iommu_ecap_sanity); +} + +bool intel_cap_flts_sanity(void) +{ + return ecap_flts(intel_iommu_ecap_sanity); +} diff --git a/drivers/iommu/intel/cap_audit.h b/drivers/iommu/intel/cap_audit.h index 866236581dd3..1ce1dc314950 100644 --- a/drivers/iommu/intel/cap_audit.h +++ b/drivers/iommu/intel/cap_audit.h @@ -103,4 +103,24 @@ enum cap_audit_type { CAP_AUDIT_HOTPLUG_IRQR, }; +bool intel_cap_smts_sanity(void); +bool intel_cap_pasid_sanity(void); +bool intel_cap_nest_sanity(void); +bool intel_cap_flts_sanity(void); + +static inline bool scalable_mode_support(void) +{ + return (intel_iommu_sm && intel_cap_smts_sanity()); +} + +static inline bool pasid_mode_support(void) +{ + return scalable_mode_support() && intel_cap_pasid_sanity(); +} + +static inline bool nested_mode_support(void) +{ + return scalable_mode_support() && intel_cap_nest_sanity(); +} + int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 592cb6dd5d3a..676f6900f4dc 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1846,25 +1846,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu) */ static bool first_level_by_default(void) { - struct dmar_drhd_unit *drhd; - struct intel_iommu *iommu; - static int first_level_support = -1; - - if (likely(first_level_support != -1)) - return first_level_support; - - first_level_support = 1; - - rcu_read_lock(); - for_each_active_iommu(iommu, drhd) { - if (!sm_supported(iommu) || !ecap_flts(iommu->ecap)) { - first_level_support = 0; - break; - } - } - rcu_read_unlock(); - - return first_level_support; + return scalable_mode_support() && intel_cap_flts_sanity(); } static struct dmar_domain *alloc_domain(int flags) @@ -5663,60 +5645,6 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, return phys; } -static inline bool scalable_mode_support(void) -{ - struct dmar_drhd_unit *drhd; - struct intel_iommu *iommu; - bool ret = true; - - rcu_read_lock(); - for_each_active_iommu(iommu, drhd) { - if (!sm_supported(iommu)) { - ret = false; - break; - } - } - rcu_read_unlock(); - - return ret; -} - -static inline bool iommu_pasid_support(void) -{ - struct dmar_drhd_unit *drhd; - struct intel_iommu *iommu; - bool ret = true; - - rcu_read_lock(); - for_each_active_iommu(iommu, drhd) { - if (!pasid_supported(iommu)) { - ret = false; - break; - } - } - rcu_read_unlock(); - - return ret; -} - -static inline bool nested_mode_support(void) -{ - struct dmar_drhd_unit *drhd; - struct intel_iommu *iommu; - bool ret = true; - - rcu_read_lock(); - for_each_active_iommu(iommu, drhd) { - if (!sm_supported(iommu) || !ecap_nest(iommu->ecap)) { - ret = false; - break; - } - } - rcu_read_unlock(); - - return ret; -} - static bool intel_iommu_capable(enum iommu_cap cap) { if (cap == IOMMU_CAP_CACHE_COHERENCY) @@ -5970,7 +5898,7 @@ intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat) int ret; if (!dev_is_pci(dev) || dmar_disabled || - !scalable_mode_support() || !iommu_pasid_support()) + !scalable_mode_support() || !pasid_mode_support()) return false; ret = pci_pasid_features(to_pci_dev(dev)); -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org
Re: [GIT PULL] dma-mapping updates for 5.11
The pull request you sent on Tue, 22 Dec 2020 17:01:12 +0100: > git://git.infradead.org/users/hch/dma-mapping.git tags/dma-mapping-5.11 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/347d81b68b8f7044c9ce3fefa130a736ca916176 Thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/3] iommu/vt-d: Track device aux-attach with subdevice_domain_info.
Hi Yi, On Sun, 20 Dec 2020 08:03:51 +0800, Liu Yi L wrote: > In existing code, if wanting to loop all devices attached to a domain, > current code can only loop the devices which are attached to the domain > via normal manner. While for devices attached via auxiliary manner, this > is subdevice, they are not tracked in the domain. This patch adds struct How about "In the existing code, loop all devices attached to a domain does not include sub-devices attached via iommu_aux_attach_device()." > subdevice_domain_info which is created per domain attachment via auxiliary > manner. So that such devices are also tracked in domain. > > This was found by when I'm working on the belwo patch, There is no device > in domain->devices, thus unable to get the cap and ecap of iommu unit. But > this domain actually has one sub-device which is attached via aux-manner. > This patch fixes the issue. > > https://lore.kernel.org/kvm/1599734733-6431-17-git-send-email-yi.l@intel.com/ > > But looks like, it doesn't affect me only. Such auxiliary track should be > there for example if wanting to flush device_iotlb for a domain which has > devices attached by auxiliray manner, then this fix is also necessary. Perhaps: This fix goes beyond the patch above, such sub-device tracking is necessary for other cases. For example, flushing device_iotlb for a domain which has sub-devices attached by auxiliary manner. > This issue will also be fixed by another patch in this series with some > additional changes based on the sudevice tracking framework introduced in > this patch. > > Co-developed-by: Xin Zeng > Signed-off-by: Xin Zeng > Co-developed-by: Liu Yi L > Signed-off-by: Liu Yi L > Co-developed-by: Lu Baolu > Signed-off-by: Lu Baolu > --- > drivers/iommu/intel/iommu.c | 92 - > include/linux/intel-iommu.h | 11 - > 2 files changed, 90 insertions(+), 13 deletions(-) > > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c > index a49afa11673c..4274b4acc325 100644 > --- a/drivers/iommu/intel/iommu.c > +++ b/drivers/iommu/intel/iommu.c > @@ -1881,6 +1881,7 @@ static struct dmar_domain *alloc_domain(int flags) > domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL; > domain->has_iotlb_device = false; > INIT_LIST_HEAD(>devices); > + INIT_LIST_HEAD(>sub_devices); > > return domain; > } > @@ -5172,33 +5173,79 @@ is_aux_domain(struct device *dev, struct > iommu_domain *domain) domain->type == IOMMU_DOMAIN_UNMANAGED; > } > > +static inline > +void _auxiliary_link_device(struct dmar_domain *domain, > + struct subdevice_domain_info *subinfo, > + struct device *dev) > +{ > + subinfo->users++; > +} > + why pass in more arguments than subinfo? the function name does not match what it does, seems just refcount inc. > +static inline > +int _auxiliary_unlink_device(struct dmar_domain *domain, > + struct subdevice_domain_info *subinfo, > + struct device *dev) > +{ > + subinfo->users--; > + return subinfo->users; ditto. why not just return subinfo->users--; > +} > + > static void auxiliary_link_device(struct dmar_domain *domain, > struct device *dev) > { > struct device_domain_info *info = get_domain_info(dev); > + struct subdevice_domain_info *subinfo; > > assert_spin_locked(_domain_lock); > if (WARN_ON(!info)) > return; > > + subinfo = kzalloc(sizeof(*subinfo), GFP_ATOMIC); > + if (!subinfo) > + return; > + > + subinfo->domain = domain; > + subinfo->dev = dev; > + list_add(>link_domain, >auxiliary_domains); > + list_add(>link_phys, >sub_devices); > + _auxiliary_link_device(domain, subinfo, dev); or just opencode subinfo->users++? > domain->auxd_refcnt++; > - list_add(>auxd, >auxiliary_domains); > } > > -static void auxiliary_unlink_device(struct dmar_domain *domain, > - struct device *dev) > +static struct subdevice_domain_info * > +subdevice_domain_info_lookup(struct dmar_domain *domain, struct device > *dev) +{ > + struct subdevice_domain_info *subinfo; > + > + assert_spin_locked(_domain_lock); > + > + list_for_each_entry(subinfo, >sub_devices, link_phys) > + if (subinfo->dev == dev) > + return subinfo; > + > + return NULL; > +} > + > +static int auxiliary_unlink_device(struct dmar_domain *domain, > +struct subdevice_domain_info *subinfo, > +struct device *dev) > { > struct device_domain_info *info = get_domain_info(dev); > + int ret; > > assert_spin_locked(_domain_lock); > if (WARN_ON(!info)) > - return; > + return -EINVAL; > > - list_del(>auxd); > + ret = _auxiliary_unlink_device(domain,
Re: [PATCH v2 1/7] iommu/io-pgtable: Introduce dynamic io-pgtable fmt registration
On 2020-12-22 11:27, Robin Murphy wrote: On 2020-12-22 00:44, Isaac J. Manjarres wrote: The io-pgtable code constructs an array of init functions for each page table format at compile time. This is not ideal, as this increases the footprint of the io-pgtable code, as well as prevents io-pgtable formats from being built as kernel modules. In preparation for modularizing the io-pgtable formats, switch to a dynamic registration scheme, where each io-pgtable format can register their init functions with the io-pgtable code at boot or module insertion time. Signed-off-by: Isaac J. Manjarres --- drivers/iommu/io-pgtable-arm-v7s.c | 34 +- drivers/iommu/io-pgtable-arm.c | 90 ++-- drivers/iommu/io-pgtable.c | 94 -- include/linux/io-pgtable.h | 51 + 4 files changed, 209 insertions(+), 60 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 1d92ac9..89aad2f 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -835,7 +836,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg, return NULL; } -struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns = { +static struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns = { + .fmt= ARM_V7S, .alloc = arm_v7s_alloc_pgtable, .free = arm_v7s_free_pgtable, }; @@ -982,5 +984,33 @@ static int __init arm_v7s_do_selftests(void) pr_info("self test ok\n"); return 0; } -subsys_initcall(arm_v7s_do_selftests); +#else +static int arm_v7s_do_selftests(void) +{ + return 0; +} #endif + +static int __init arm_v7s_init(void) +{ + int ret; + + ret = io_pgtable_ops_register(_pgtable_arm_v7s_init_fns); + if (ret < 0) { + pr_err("Failed to register ARM V7S format\n"); Super-nit: I think "v7s" should probably be lowercase there. Also general consistency WRT to showing the error code and whether or not to abbreviate "format" would be nice. Ok, I can fix this accordingly. + return ret; + } + + ret = arm_v7s_do_selftests(); + if (ret < 0) + io_pgtable_ops_unregister(_pgtable_arm_v7s_init_fns); + + return ret; +} +core_initcall(arm_v7s_init); + +static void __exit arm_v7s_exit(void) +{ + io_pgtable_ops_unregister(_pgtable_arm_v7s_init_fns); +} +module_exit(arm_v7s_exit); diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 87def58..ff0ea2f 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1043,29 +1044,32 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) return NULL; } -struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { - .alloc = arm_64_lpae_alloc_pgtable_s1, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns = { - .alloc = arm_64_lpae_alloc_pgtable_s2, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns = { - .alloc = arm_32_lpae_alloc_pgtable_s1, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns = { - .alloc = arm_32_lpae_alloc_pgtable_s2, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = { - .alloc = arm_mali_lpae_alloc_pgtable, - .free = arm_lpae_free_pgtable, +static struct io_pgtable_init_fns io_pgtable_arm_lpae_init_fns[] = { + { + .fmt= ARM_32_LPAE_S1, + .alloc = arm_32_lpae_alloc_pgtable_s1, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_32_LPAE_S2, + .alloc = arm_32_lpae_alloc_pgtable_s2, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_64_LPAE_S1, + .alloc = arm_64_lpae_alloc_pgtable_s1, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_64_LPAE_S2, + .alloc = arm_64_lpae_alloc_pgtable_s2, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_MALI_LPAE, + .alloc = arm_mali_lpae_alloc_pgtable, + .free = arm_lpae_free_pgtable, + }, }; #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST @@ -1250,5 +1254,43 @@ static int __init arm_lpae_do_selftests(void) pr_info("selftest: completed with %d PASS %d FAIL\n", pass, fail); return fail ? -EFAULT : 0; }
Re: [PATCH v2 3/7] iommu/arm-smmu: Add dependency on io-pgtable format modules
On 2020-12-22 11:27, Robin Murphy wrote: On 2020-12-22 00:44, Isaac J. Manjarres wrote: The SMMU driver depends on the availability of the ARM LPAE and ARM V7S io-pgtable format code to work properly. In preparation Nit: we don't really depend on v7s - we *can* use it if it's available, address constraints are suitable, and the SMMU implementation actually supports it (many don't), but we can still quite happily not use it even so. LPAE is mandatory in the architecture so that's our only hard requirement, embodied in the kconfig select. This does mean there may technically still be a corner case involving ARM_SMMU=y and IO_PGTABLE_ARM_V7S=m, but at worst it's now a runtime failure rather than a build error, so unless and until anyone demonstrates that it actually matters I don't feel particularly inclined to give it much thought. Robin. Okay, I'll fix up the commit message, as well as the code, so that it only depends on io-pgtable-arm. Thanks, Isaac for having the io-pgtable formats as modules, add a "pre" dependency with MODULE_SOFTDEP() to ensure that the io-pgtable format modules are loaded before loading the ARM SMMU driver module. Signed-off-by: Isaac J. Manjarres --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index d8c6bfd..a72649f 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -2351,3 +2351,4 @@ MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); MODULE_AUTHOR("Will Deacon "); MODULE_ALIAS("platform:arm-smmu"); MODULE_LICENSE("GPL v2"); +MODULE_SOFTDEP("pre: io-pgtable-arm io-pgtable-arm-v7s"); ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 1/7] iommu/io-pgtable: Introduce dynamic io-pgtable fmt registration
On 2020-12-22 00:44, Isaac J. Manjarres wrote: The io-pgtable code constructs an array of init functions for each page table format at compile time. This is not ideal, as this increases the footprint of the io-pgtable code, as well as prevents io-pgtable formats from being built as kernel modules. In preparation for modularizing the io-pgtable formats, switch to a dynamic registration scheme, where each io-pgtable format can register their init functions with the io-pgtable code at boot or module insertion time. Signed-off-by: Isaac J. Manjarres --- drivers/iommu/io-pgtable-arm-v7s.c | 34 +- drivers/iommu/io-pgtable-arm.c | 90 ++-- drivers/iommu/io-pgtable.c | 94 -- include/linux/io-pgtable.h | 51 + 4 files changed, 209 insertions(+), 60 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index 1d92ac9..89aad2f 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -835,7 +836,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg, return NULL; } -struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns = { +static struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns = { + .fmt= ARM_V7S, .alloc = arm_v7s_alloc_pgtable, .free = arm_v7s_free_pgtable, }; @@ -982,5 +984,33 @@ static int __init arm_v7s_do_selftests(void) pr_info("self test ok\n"); return 0; } -subsys_initcall(arm_v7s_do_selftests); +#else +static int arm_v7s_do_selftests(void) +{ + return 0; +} #endif + +static int __init arm_v7s_init(void) +{ + int ret; + + ret = io_pgtable_ops_register(_pgtable_arm_v7s_init_fns); + if (ret < 0) { + pr_err("Failed to register ARM V7S format\n"); Super-nit: I think "v7s" should probably be lowercase there. Also general consistency WRT to showing the error code and whether or not to abbreviate "format" would be nice. + return ret; + } + + ret = arm_v7s_do_selftests(); + if (ret < 0) + io_pgtable_ops_unregister(_pgtable_arm_v7s_init_fns); + + return ret; +} +core_initcall(arm_v7s_init); + +static void __exit arm_v7s_exit(void) +{ + io_pgtable_ops_unregister(_pgtable_arm_v7s_init_fns); +} +module_exit(arm_v7s_exit); diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 87def58..ff0ea2f 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1043,29 +1044,32 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) return NULL; } -struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { - .alloc = arm_64_lpae_alloc_pgtable_s1, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns = { - .alloc = arm_64_lpae_alloc_pgtable_s2, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns = { - .alloc = arm_32_lpae_alloc_pgtable_s1, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns = { - .alloc = arm_32_lpae_alloc_pgtable_s2, - .free = arm_lpae_free_pgtable, -}; - -struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = { - .alloc = arm_mali_lpae_alloc_pgtable, - .free = arm_lpae_free_pgtable, +static struct io_pgtable_init_fns io_pgtable_arm_lpae_init_fns[] = { + { + .fmt= ARM_32_LPAE_S1, + .alloc = arm_32_lpae_alloc_pgtable_s1, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_32_LPAE_S2, + .alloc = arm_32_lpae_alloc_pgtable_s2, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_64_LPAE_S1, + .alloc = arm_64_lpae_alloc_pgtable_s1, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_64_LPAE_S2, + .alloc = arm_64_lpae_alloc_pgtable_s2, + .free = arm_lpae_free_pgtable, + }, + { + .fmt= ARM_MALI_LPAE, + .alloc = arm_mali_lpae_alloc_pgtable, + .free = arm_lpae_free_pgtable, + }, }; #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST @@ -1250,5 +1254,43 @@ static int __init arm_lpae_do_selftests(void) pr_info("selftest: completed with %d PASS %d FAIL\n", pass, fail); return fail ? -EFAULT : 0; } -subsys_initcall(arm_lpae_do_selftests); +#else +static int __init
Re: [PATCH v2 3/7] iommu/arm-smmu: Add dependency on io-pgtable format modules
On 2020-12-22 00:44, Isaac J. Manjarres wrote: The SMMU driver depends on the availability of the ARM LPAE and ARM V7S io-pgtable format code to work properly. In preparation Nit: we don't really depend on v7s - we *can* use it if it's available, address constraints are suitable, and the SMMU implementation actually supports it (many don't), but we can still quite happily not use it even so. LPAE is mandatory in the architecture so that's our only hard requirement, embodied in the kconfig select. This does mean there may technically still be a corner case involving ARM_SMMU=y and IO_PGTABLE_ARM_V7S=m, but at worst it's now a runtime failure rather than a build error, so unless and until anyone demonstrates that it actually matters I don't feel particularly inclined to give it much thought. Robin. for having the io-pgtable formats as modules, add a "pre" dependency with MODULE_SOFTDEP() to ensure that the io-pgtable format modules are loaded before loading the ARM SMMU driver module. Signed-off-by: Isaac J. Manjarres --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index d8c6bfd..a72649f 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -2351,3 +2351,4 @@ MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); MODULE_AUTHOR("Will Deacon "); MODULE_ALIAS("platform:arm-smmu"); MODULE_LICENSE("GPL v2"); +MODULE_SOFTDEP("pre: io-pgtable-arm io-pgtable-arm-v7s"); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/4] iommu/vtd-: Misc fixes on scalable mode
Hi Yi, nit: The cover letter is 0/4, patches are 1/3 - 3/3. You also need to copy LKML. On Sun, 20 Dec 2020 08:03:49 +0800, Liu Yi L wrote: > Hi, > > This patchset aims to fix a bug regards to SVM usage on native, and perhaps 'native SVM usage' > also several bugs around subdevice (attached to device via auxiliary > manner) tracking and ineffective device_tlb flush. > > Regards, > Yi Liu > > Liu Yi L (3): > iommu/vt-d: Move intel_iommu info from struct intel_svm to struct > intel_svm_dev > iommu/vt-d: Track device aux-attach with subdevice_domain_info. > iommu/vt-d: A fix to iommu_flush_dev_iotlb() for aux-domain > > drivers/iommu/intel/iommu.c | 182 ++-- > drivers/iommu/intel/svm.c | 9 +- > include/linux/intel-iommu.h | 13 ++- > 3 files changed, 168 insertions(+), 36 deletions(-) > Thanks, Jacob ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/iova: fix 'domain' typos
Replace misspelled 'doamin' with 'domain' in several comments. Signed-off-by: Stefano Garzarella --- drivers/iommu/iova.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 4bb3293ae4d7..d20b8b333d30 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -358,7 +358,7 @@ static void private_free_iova(struct iova_domain *iovad, struct iova *iova) * @iovad: - iova domain in question. * @pfn: - page frame number * This function finds and returns an iova belonging to the - * given doamin which matches the given pfn. + * given domain which matches the given pfn. */ struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn) { @@ -601,7 +601,7 @@ void queue_iova(struct iova_domain *iovad, EXPORT_SYMBOL_GPL(queue_iova); /** - * put_iova_domain - destroys the iova doamin + * put_iova_domain - destroys the iova domain * @iovad: - iova domain in question. * All the iova's in that domain are destroyed. */ @@ -712,9 +712,9 @@ EXPORT_SYMBOL_GPL(reserve_iova); /** * copy_reserved_iova - copies the reserved between domains - * @from: - source doamin from where to copy + * @from: - source domain from where to copy * @to: - destination domin where to copy - * This function copies reserved iova's from one doamin to + * This function copies reserved iova's from one domain to * other. */ void -- 2.26.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[GIT PULL] dma-mapping updates for 5.11
The following changes since commit 418baf2c28f3473039f2f7377760bd8f6897ae18: Linux 5.10-rc5 (2020-11-22 15:36:08 -0800) are available in the Git repository at: git://git.infradead.org/users/hch/dma-mapping.git tags/dma-mapping-5.11 for you to fetch changes up to 7679325702c90aecd393cd7cde685576c14489c0: selftests/dma: add test application for DMA_MAP_BENCHMARK (2020-11-27 10:33:42 +0100) dma-mapping updates for 5.11: - support for a partial IOMMU bypass (Alexey Kardashevskiy) - add a DMA API benchmark (Barry Song) - misc fixes (Tiezhu Yang, tangjianqiang) Alexey Kardashevskiy (2): dma-mapping: Allow mixing bypass and mapped DMA operation powerpc/dma: Fallback to dma_ops when persistent memory present Barry Song (2): dma-mapping: add benchmark support for streaming DMA APIs selftests/dma: add test application for DMA_MAP_BENCHMARK Tiezhu Yang (1): dma-pool: no need to check return value of debugfs_create functions tangjianqiang (1): dma-contiguous: fix a typo error in a comment MAINTAINERS | 6 + arch/powerpc/Kconfig| 1 + arch/powerpc/kernel/dma-iommu.c | 71 - arch/powerpc/platforms/pseries/iommu.c | 51 +++- include/linux/dma-map-ops.h | 14 + kernel/dma/Kconfig | 13 + kernel/dma/Makefile | 1 + kernel/dma/contiguous.c | 2 +- kernel/dma/map_benchmark.c | 361 kernel/dma/mapping.c| 12 +- kernel/dma/pool.c | 3 - tools/testing/selftests/dma/Makefile| 6 + tools/testing/selftests/dma/config | 1 + tools/testing/selftests/dma/dma_map_benchmark.c | 123 14 files changed, 645 insertions(+), 20 deletions(-) create mode 100644 kernel/dma/map_benchmark.c create mode 100644 tools/testing/selftests/dma/Makefile create mode 100644 tools/testing/selftests/dma/config create mode 100644 tools/testing/selftests/dma/dma_map_benchmark.c ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu