Loading drivers/iommu/arm-smmu.c +53 −2 Original line number Diff line number Diff line Loading @@ -273,6 +273,7 @@ struct arm_smmu_device { u32 num_context_banks; u32 num_s2_context_banks; DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS); DECLARE_BITMAP(secure_context_map, ARM_SMMU_MAX_CBS); struct arm_smmu_cb *cbs; atomic_t irptndx; Loading Loading @@ -2785,6 +2786,11 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) arm_smmu_unassign_table(smmu_domain); arm_smmu_secure_domain_unlock(smmu_domain); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); /* As the nonsecure context bank index is any way set to zero, * so, directly clearing up the secure cb bitmap. */ if (arm_smmu_is_slave_side_secure(smmu_domain)) __arm_smmu_free_bitmap(smmu->secure_context_map, cfg->cbndx); arm_smmu_power_off(smmu->pwr); arm_smmu_domain_reinit(smmu_domain); Loading Loading @@ -3916,6 +3922,46 @@ static size_t msm_secure_smmu_map_sg(struct iommu_domain *domain, return ret; } void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr) { struct arm_smmu_device *smmu = NULL; unsigned long base, mask; smmu = arm_smmu_get_by_fwnode(iommu->fwnode); if (!smmu) return NULL; base = (unsigned long)smmu->base; mask = ~(smmu->size - 1); if ((base & mask) == ((unsigned long)addr & mask)) return (void *)smmu; return NULL; } bool arm_smmu_skip_write(void __iomem *addr) { struct arm_smmu_device *smmu; int cb; smmu = arm_smmu_get_by_addr(addr); /* Skip write if smmu not available by now */ if (!smmu) return true; /* Do not write to global space */ if (((unsigned long)addr & (smmu->size - 1)) < (smmu->size >> 1)) return true; /* Finally skip writing to secure CB */ cb = ((unsigned long)addr & ((smmu->size >> 1) - 1)) >> PAGE_SHIFT; if (test_bit(cb, smmu->secure_context_map)) return true; return false; } #endif static int arm_smmu_add_device(struct device *dev) Loading Loading @@ -4956,9 +5002,13 @@ static int arm_smmu_alloc_cb(struct iommu_domain *domain, cb = smmu->s2crs[idx].cbndx; } if (cb >= 0 && arm_smmu_is_static_cb(smmu)) if (cb >= 0 && arm_smmu_is_static_cb(smmu)) { smmu_domain->slave_side_secure = true; if (arm_smmu_is_slave_side_secure(smmu_domain)) bitmap_set(smmu->secure_context_map, cb, 1); } if (cb < 0 && !arm_smmu_is_static_cb(smmu)) { mutex_unlock(&smmu->stream_map_mutex); return __arm_smmu_alloc_bitmap(smmu->context_map, Loading Loading @@ -5765,7 +5815,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev) if (arm_smmu_power_on(smmu->pwr)) return -EINVAL; if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS) || !bitmap_empty(smmu->secure_context_map, ARM_SMMU_MAX_CBS)) dev_err(&pdev->dev, "removing device with active domains!\n"); idr_destroy(&smmu->asid_idr); Loading drivers/iommu/iommu.c +23 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ #include <linux/debugfs.h> #include <linux/property.h> #include <trace/events/iommu.h> #ifdef CONFIG_MSM_TZ_SMMU #include <soc/qcom/msm_tz_smmu.h> #endif static struct kset *iommu_group_kset; static DEFINE_IDA(iommu_group_ida); Loading Loading @@ -133,6 +136,26 @@ void iommu_device_unregister(struct iommu_device *iommu) spin_unlock(&iommu_device_lock); } #ifdef CONFIG_MSM_TZ_SMMU void *arm_smmu_get_by_addr(void __iomem *addr) { struct iommu_device *iommu; unsigned long flags; void *smmu = NULL; spin_lock_irqsave(&iommu_device_lock, flags); list_for_each_entry(iommu, &iommu_device_list, list) { smmu = get_smmu_from_addr(iommu, addr); if (!smmu) continue; break; } spin_unlock_irqrestore(&iommu_device_lock, flags); return smmu; } #endif static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, unsigned type); static int __iommu_attach_device(struct iommu_domain *domain, Loading include/soc/qcom/msm_tz_smmu.h +12 −1 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. * Copyright (c) 2015-2018,2021, The Linux Foundation. All rights reserved. */ #ifndef __MSM_TZ_SMMU_H__ #define __MSM_TZ_SMMU_H__ #include <linux/device.h> #include <linux/iommu.h> enum tz_smmu_device_id { TZ_DEVICE_START = 0, Loading Loading @@ -49,6 +50,16 @@ enum tz_smmu_device_id msm_dev_to_device_id(struct device *dev); int msm_tz_set_cb_format(enum tz_smmu_device_id sec_id, int cbndx); int msm_iommu_sec_pgtbl_init(void); int register_iommu_sec_ptbl(void); bool arm_smmu_skip_write(void __iomem *addr); extern void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr); extern void *arm_smmu_get_by_addr(void __iomem *addr); /* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */ #undef writel_relaxed #define writel_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writel((u32)cpu_to_le32(v), (c))); \ } while (0) #else static inline int msm_tz_smmu_atos_start(struct device *dev, int cb_num) Loading Loading
drivers/iommu/arm-smmu.c +53 −2 Original line number Diff line number Diff line Loading @@ -273,6 +273,7 @@ struct arm_smmu_device { u32 num_context_banks; u32 num_s2_context_banks; DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS); DECLARE_BITMAP(secure_context_map, ARM_SMMU_MAX_CBS); struct arm_smmu_cb *cbs; atomic_t irptndx; Loading Loading @@ -2785,6 +2786,11 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) arm_smmu_unassign_table(smmu_domain); arm_smmu_secure_domain_unlock(smmu_domain); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); /* As the nonsecure context bank index is any way set to zero, * so, directly clearing up the secure cb bitmap. */ if (arm_smmu_is_slave_side_secure(smmu_domain)) __arm_smmu_free_bitmap(smmu->secure_context_map, cfg->cbndx); arm_smmu_power_off(smmu->pwr); arm_smmu_domain_reinit(smmu_domain); Loading Loading @@ -3916,6 +3922,46 @@ static size_t msm_secure_smmu_map_sg(struct iommu_domain *domain, return ret; } void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr) { struct arm_smmu_device *smmu = NULL; unsigned long base, mask; smmu = arm_smmu_get_by_fwnode(iommu->fwnode); if (!smmu) return NULL; base = (unsigned long)smmu->base; mask = ~(smmu->size - 1); if ((base & mask) == ((unsigned long)addr & mask)) return (void *)smmu; return NULL; } bool arm_smmu_skip_write(void __iomem *addr) { struct arm_smmu_device *smmu; int cb; smmu = arm_smmu_get_by_addr(addr); /* Skip write if smmu not available by now */ if (!smmu) return true; /* Do not write to global space */ if (((unsigned long)addr & (smmu->size - 1)) < (smmu->size >> 1)) return true; /* Finally skip writing to secure CB */ cb = ((unsigned long)addr & ((smmu->size >> 1) - 1)) >> PAGE_SHIFT; if (test_bit(cb, smmu->secure_context_map)) return true; return false; } #endif static int arm_smmu_add_device(struct device *dev) Loading Loading @@ -4956,9 +5002,13 @@ static int arm_smmu_alloc_cb(struct iommu_domain *domain, cb = smmu->s2crs[idx].cbndx; } if (cb >= 0 && arm_smmu_is_static_cb(smmu)) if (cb >= 0 && arm_smmu_is_static_cb(smmu)) { smmu_domain->slave_side_secure = true; if (arm_smmu_is_slave_side_secure(smmu_domain)) bitmap_set(smmu->secure_context_map, cb, 1); } if (cb < 0 && !arm_smmu_is_static_cb(smmu)) { mutex_unlock(&smmu->stream_map_mutex); return __arm_smmu_alloc_bitmap(smmu->context_map, Loading Loading @@ -5765,7 +5815,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev) if (arm_smmu_power_on(smmu->pwr)) return -EINVAL; if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS)) if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS) || !bitmap_empty(smmu->secure_context_map, ARM_SMMU_MAX_CBS)) dev_err(&pdev->dev, "removing device with active domains!\n"); idr_destroy(&smmu->asid_idr); Loading
drivers/iommu/iommu.c +23 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ #include <linux/debugfs.h> #include <linux/property.h> #include <trace/events/iommu.h> #ifdef CONFIG_MSM_TZ_SMMU #include <soc/qcom/msm_tz_smmu.h> #endif static struct kset *iommu_group_kset; static DEFINE_IDA(iommu_group_ida); Loading Loading @@ -133,6 +136,26 @@ void iommu_device_unregister(struct iommu_device *iommu) spin_unlock(&iommu_device_lock); } #ifdef CONFIG_MSM_TZ_SMMU void *arm_smmu_get_by_addr(void __iomem *addr) { struct iommu_device *iommu; unsigned long flags; void *smmu = NULL; spin_lock_irqsave(&iommu_device_lock, flags); list_for_each_entry(iommu, &iommu_device_list, list) { smmu = get_smmu_from_addr(iommu, addr); if (!smmu) continue; break; } spin_unlock_irqrestore(&iommu_device_lock, flags); return smmu; } #endif static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, unsigned type); static int __iommu_attach_device(struct iommu_domain *domain, Loading
include/soc/qcom/msm_tz_smmu.h +12 −1 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. * Copyright (c) 2015-2018,2021, The Linux Foundation. All rights reserved. */ #ifndef __MSM_TZ_SMMU_H__ #define __MSM_TZ_SMMU_H__ #include <linux/device.h> #include <linux/iommu.h> enum tz_smmu_device_id { TZ_DEVICE_START = 0, Loading Loading @@ -49,6 +50,16 @@ enum tz_smmu_device_id msm_dev_to_device_id(struct device *dev); int msm_tz_set_cb_format(enum tz_smmu_device_id sec_id, int cbndx); int msm_iommu_sec_pgtbl_init(void); int register_iommu_sec_ptbl(void); bool arm_smmu_skip_write(void __iomem *addr); extern void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr); extern void *arm_smmu_get_by_addr(void __iomem *addr); /* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */ #undef writel_relaxed #define writel_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writel((u32)cpu_to_le32(v), (c))); \ } while (0) #else static inline int msm_tz_smmu_atos_start(struct device *dev, int cb_num) Loading