Loading drivers/iommu/Kconfig +11 −14 Original line number Diff line number Diff line Loading @@ -367,6 +367,14 @@ config SPAPR_TCE_IOMMU Enables bits of IOMMU API required by VFIO. The iommu_ops is not implemented as it is not necessary for VFIO. config QTI_IOMMU_SUPPORT tristate "Support for QTI iommu drivers" help The QTI GPU device may switch between multiple iommu domains, depending on usecase. This introduces a need to track all such domains in a non-driver specific manner. If in doubt say N. # ARM IOMMU support config ARM_SMMU bool "ARM Ltd. System MMU (SMMU) Support" Loading @@ -375,6 +383,7 @@ config ARM_SMMU select IOMMU_IO_PGTABLE_LPAE select ARM_DMA_USE_IOMMU if ARM select ARM64_DMA_USE_IOMMU if ARM64 select QTI_IOMMU_SUPPORT help Support for implementations of the ARM System MMU architecture versions 1 and 2. Loading Loading @@ -495,26 +504,14 @@ menuconfig IOMMU_DEBUG if IOMMU_DEBUG config IOMMU_DEBUG_TRACKING bool "Track key IOMMU events" select IOMMU_API help Enables additional debug tracking in the IOMMU framework code. Tracking information and tests can be accessed through various debugfs files. Say Y here if you need to debug IOMMU issues and are okay with the performance penalty of the tracking. config IOMMU_TESTS bool "Interactive IOMMU performance/functional tests" select IOMMU_API select ARM64_PTDUMP_CORE help Enables a suite of IOMMU unit tests. The tests are runnable through debugfs. Unlike the IOMMU_DEBUG_TRACKING option, the impact of enabling this option to overal system performance should be minimal. through debugfs. The impact of enabling this option to overall system performance should be minimal. endif # IOMMU_DEBUG Loading drivers/iommu/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -34,4 +34,5 @@ obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o obj-$(CONFIG_S390_IOMMU) += s390-iommu.o obj-$(CONFIG_QTI_IOMMU_SUPPORT) += iommu-logger.o obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o drivers/iommu/arm-smmu.c +16 −4 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #include "io-pgtable.h" #include "arm-smmu-regs.h" #include "arm-smmu-debug.h" #include "iommu-logger.h" #include <linux/debugfs.h> #include <linux/uaccess.h> Loading Loading @@ -394,6 +395,7 @@ struct arm_smmu_domain { struct list_head secure_pool_list; /* nonsecure pool protected by pgtbl_lock */ struct list_head nonsecure_pool; struct iommu_debug_attachment *logger; struct iommu_domain domain; }; Loading Loading @@ -2079,17 +2081,24 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, struct arm_smmu_cfg *cfg = &smmu_domain->cfg; unsigned long quirks = 0; bool dynamic; struct iommu_group *group; mutex_lock(&smmu_domain->init_mutex); if (smmu_domain->smmu) goto out_unlock; group = iommu_group_get(dev); ret = iommu_logger_register(&smmu_domain->logger, domain, group); iommu_group_put(group); if (ret) goto out_unlock; if (domain->type == IOMMU_DOMAIN_DMA) { ret = arm_smmu_setup_default_domain(dev, domain); if (ret) { dev_err(dev, "%s: default domain setup failed\n", __func__); goto out_unlock; goto out_logger; } } Loading Loading @@ -2147,7 +2156,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, if (cfg->fmt == ARM_SMMU_CTX_FMT_NONE) { ret = -EINVAL; goto out_unlock; goto out_logger; } switch (smmu_domain->stage) { Loading Loading @@ -2195,7 +2204,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, break; default: ret = -EINVAL; goto out_unlock; goto out_logger; } if (smmu_domain->attributes & (1 << DOMAIN_ATTR_FAST)) Loading @@ -2217,7 +2226,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, ret = arm_smmu_alloc_cb(domain, smmu, dev); if (ret < 0) goto out_unlock; goto out_logger; cfg->cbndx = ret; Loading Loading @@ -2325,6 +2334,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, out_clear_smmu: arm_smmu_destroy_domain_context(domain); smmu_domain->smmu = NULL; out_logger: iommu_logger_unregister(smmu_domain->logger); out_unlock: mutex_unlock(&smmu_domain->init_mutex); return ret; Loading Loading @@ -2448,6 +2459,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) */ arm_smmu_put_dma_cookie(domain); arm_smmu_destroy_domain_context(domain); iommu_logger_unregister(smmu_domain->logger); kfree(smmu_domain); } Loading drivers/iommu/iommu-debug.c +0 −62 Original line number Diff line number Diff line Loading @@ -86,68 +86,6 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr) } #endif #ifdef CONFIG_IOMMU_DEBUG_TRACKING static DEFINE_MUTEX(iommu_debug_attachments_lock); static LIST_HEAD(iommu_debug_attachments); /* * Each group may have more than one domain; but each domain may * only have one group. * Used by debug tools to display the name of the device(s) associated * with a particular domain. */ struct iommu_debug_attachment { struct iommu_domain *domain; struct iommu_group *group; struct list_head list; }; void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev) { struct iommu_debug_attachment *attach; struct iommu_group *group; group = dev->iommu_group; if (!group) return; mutex_lock(&iommu_debug_attachments_lock); list_for_each_entry(attach, &iommu_debug_attachments, list) if ((attach->domain == domain) && (attach->group == group)) goto out; attach = kzalloc(sizeof(*attach), GFP_KERNEL); if (!attach) goto out; attach->domain = domain; attach->group = group; INIT_LIST_HEAD(&attach->list); list_add(&attach->list, &iommu_debug_attachments); out: mutex_unlock(&iommu_debug_attachments_lock); } void iommu_debug_domain_remove(struct iommu_domain *domain) { struct iommu_debug_attachment *it, *tmp; mutex_lock(&iommu_debug_attachments_lock); list_for_each_entry_safe(it, tmp, &iommu_debug_attachments, list) { if (it->domain != domain) continue; list_del(&it->list); kfree(it); } mutex_unlock(&iommu_debug_attachments_lock); } #endif #ifdef CONFIG_IOMMU_TESTS #ifdef CONFIG_64BIT Loading drivers/iommu/iommu-debug.hdeleted 100644 → 0 +0 −27 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ #ifndef IOMMU_DEBUG_H #define IOMMU_DEBUG_H #ifdef CONFIG_IOMMU_DEBUG_TRACKING void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev); void iommu_debug_domain_remove(struct iommu_domain *domain); #else /* !CONFIG_IOMMU_DEBUG_TRACKING */ static inline void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev) { } static inline void iommu_debug_domain_remove(struct iommu_domain *domain) { } #endif /* CONFIG_IOMMU_DEBUG_TRACKING */ #endif /* IOMMU_DEBUG_H */ Loading
drivers/iommu/Kconfig +11 −14 Original line number Diff line number Diff line Loading @@ -367,6 +367,14 @@ config SPAPR_TCE_IOMMU Enables bits of IOMMU API required by VFIO. The iommu_ops is not implemented as it is not necessary for VFIO. config QTI_IOMMU_SUPPORT tristate "Support for QTI iommu drivers" help The QTI GPU device may switch between multiple iommu domains, depending on usecase. This introduces a need to track all such domains in a non-driver specific manner. If in doubt say N. # ARM IOMMU support config ARM_SMMU bool "ARM Ltd. System MMU (SMMU) Support" Loading @@ -375,6 +383,7 @@ config ARM_SMMU select IOMMU_IO_PGTABLE_LPAE select ARM_DMA_USE_IOMMU if ARM select ARM64_DMA_USE_IOMMU if ARM64 select QTI_IOMMU_SUPPORT help Support for implementations of the ARM System MMU architecture versions 1 and 2. Loading Loading @@ -495,26 +504,14 @@ menuconfig IOMMU_DEBUG if IOMMU_DEBUG config IOMMU_DEBUG_TRACKING bool "Track key IOMMU events" select IOMMU_API help Enables additional debug tracking in the IOMMU framework code. Tracking information and tests can be accessed through various debugfs files. Say Y here if you need to debug IOMMU issues and are okay with the performance penalty of the tracking. config IOMMU_TESTS bool "Interactive IOMMU performance/functional tests" select IOMMU_API select ARM64_PTDUMP_CORE help Enables a suite of IOMMU unit tests. The tests are runnable through debugfs. Unlike the IOMMU_DEBUG_TRACKING option, the impact of enabling this option to overal system performance should be minimal. through debugfs. The impact of enabling this option to overall system performance should be minimal. endif # IOMMU_DEBUG Loading
drivers/iommu/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -34,4 +34,5 @@ obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o obj-$(CONFIG_S390_IOMMU) += s390-iommu.o obj-$(CONFIG_QTI_IOMMU_SUPPORT) += iommu-logger.o obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o
drivers/iommu/arm-smmu.c +16 −4 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #include "io-pgtable.h" #include "arm-smmu-regs.h" #include "arm-smmu-debug.h" #include "iommu-logger.h" #include <linux/debugfs.h> #include <linux/uaccess.h> Loading Loading @@ -394,6 +395,7 @@ struct arm_smmu_domain { struct list_head secure_pool_list; /* nonsecure pool protected by pgtbl_lock */ struct list_head nonsecure_pool; struct iommu_debug_attachment *logger; struct iommu_domain domain; }; Loading Loading @@ -2079,17 +2081,24 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, struct arm_smmu_cfg *cfg = &smmu_domain->cfg; unsigned long quirks = 0; bool dynamic; struct iommu_group *group; mutex_lock(&smmu_domain->init_mutex); if (smmu_domain->smmu) goto out_unlock; group = iommu_group_get(dev); ret = iommu_logger_register(&smmu_domain->logger, domain, group); iommu_group_put(group); if (ret) goto out_unlock; if (domain->type == IOMMU_DOMAIN_DMA) { ret = arm_smmu_setup_default_domain(dev, domain); if (ret) { dev_err(dev, "%s: default domain setup failed\n", __func__); goto out_unlock; goto out_logger; } } Loading Loading @@ -2147,7 +2156,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, if (cfg->fmt == ARM_SMMU_CTX_FMT_NONE) { ret = -EINVAL; goto out_unlock; goto out_logger; } switch (smmu_domain->stage) { Loading Loading @@ -2195,7 +2204,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, break; default: ret = -EINVAL; goto out_unlock; goto out_logger; } if (smmu_domain->attributes & (1 << DOMAIN_ATTR_FAST)) Loading @@ -2217,7 +2226,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, ret = arm_smmu_alloc_cb(domain, smmu, dev); if (ret < 0) goto out_unlock; goto out_logger; cfg->cbndx = ret; Loading Loading @@ -2325,6 +2334,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, out_clear_smmu: arm_smmu_destroy_domain_context(domain); smmu_domain->smmu = NULL; out_logger: iommu_logger_unregister(smmu_domain->logger); out_unlock: mutex_unlock(&smmu_domain->init_mutex); return ret; Loading Loading @@ -2448,6 +2459,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) */ arm_smmu_put_dma_cookie(domain); arm_smmu_destroy_domain_context(domain); iommu_logger_unregister(smmu_domain->logger); kfree(smmu_domain); } Loading
drivers/iommu/iommu-debug.c +0 −62 Original line number Diff line number Diff line Loading @@ -86,68 +86,6 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr) } #endif #ifdef CONFIG_IOMMU_DEBUG_TRACKING static DEFINE_MUTEX(iommu_debug_attachments_lock); static LIST_HEAD(iommu_debug_attachments); /* * Each group may have more than one domain; but each domain may * only have one group. * Used by debug tools to display the name of the device(s) associated * with a particular domain. */ struct iommu_debug_attachment { struct iommu_domain *domain; struct iommu_group *group; struct list_head list; }; void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev) { struct iommu_debug_attachment *attach; struct iommu_group *group; group = dev->iommu_group; if (!group) return; mutex_lock(&iommu_debug_attachments_lock); list_for_each_entry(attach, &iommu_debug_attachments, list) if ((attach->domain == domain) && (attach->group == group)) goto out; attach = kzalloc(sizeof(*attach), GFP_KERNEL); if (!attach) goto out; attach->domain = domain; attach->group = group; INIT_LIST_HEAD(&attach->list); list_add(&attach->list, &iommu_debug_attachments); out: mutex_unlock(&iommu_debug_attachments_lock); } void iommu_debug_domain_remove(struct iommu_domain *domain) { struct iommu_debug_attachment *it, *tmp; mutex_lock(&iommu_debug_attachments_lock); list_for_each_entry_safe(it, tmp, &iommu_debug_attachments, list) { if (it->domain != domain) continue; list_del(&it->list); kfree(it); } mutex_unlock(&iommu_debug_attachments_lock); } #endif #ifdef CONFIG_IOMMU_TESTS #ifdef CONFIG_64BIT Loading
drivers/iommu/iommu-debug.hdeleted 100644 → 0 +0 −27 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ #ifndef IOMMU_DEBUG_H #define IOMMU_DEBUG_H #ifdef CONFIG_IOMMU_DEBUG_TRACKING void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev); void iommu_debug_domain_remove(struct iommu_domain *domain); #else /* !CONFIG_IOMMU_DEBUG_TRACKING */ static inline void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev) { } static inline void iommu_debug_domain_remove(struct iommu_domain *domain) { } #endif /* CONFIG_IOMMU_DEBUG_TRACKING */ #endif /* IOMMU_DEBUG_H */