Loading drivers/iommu/arm-smmu.c +31 −9 Original line number Diff line number Diff line Loading @@ -355,11 +355,13 @@ struct arm_smmu_s2cr { enum arm_smmu_s2cr_privcfg privcfg; u8 cbndx; bool cb_handoff; bool write_protected; }; #define s2cr_init_val (struct arm_smmu_s2cr){ \ .type = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS, \ .cb_handoff = false, \ .write_protected = false, \ } struct arm_smmu_smr { Loading Loading @@ -627,7 +629,7 @@ static bool is_dynamic_domain(struct iommu_domain *domain) return !!(smmu_domain->attributes & (1 << DOMAIN_ATTR_DYNAMIC)); } static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu) static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu, u32 cb) { int ret; int scm_ret = 0; Loading @@ -635,7 +637,7 @@ static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu) if (!arm_smmu_is_static_cb(smmu)) return 0; ret = scm_restore_sec_cfg(smmu->sec_id, 0x0, &scm_ret); ret = scm_restore_sec_cfg(smmu->sec_id, cb, &scm_ret); if (ret || scm_ret) { pr_err("scm call IOMMU_SECURE_CFG failed\n"); return -EINVAL; Loading Loading @@ -2758,14 +2760,29 @@ static struct arm_smmu_device *arm_smmu_get_by_addr(void __iomem *addr) bool arm_smmu_skip_write(void __iomem *addr) { struct arm_smmu_device *smmu; unsigned long cb; int i; smmu = arm_smmu_get_by_addr(addr); if (smmu && ((unsigned long)addr & (smmu->size - 1)) >= (smmu->size >> 1)) return false; else /* 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; for (i = 0; i < smmu->num_mapping_groups; i++) { if ((smmu->s2crs[i].cbndx == cb) && (smmu->s2crs[i].write_protected)) return true; } return false; } #endif static struct arm_smmu_device *arm_smmu_get_by_list(struct device_node *np) Loading Loading @@ -3698,9 +3715,14 @@ 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)) for_each_cfg_sme(fwspec, i, idx) smmu->s2crs[idx].write_protected = true; } 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 @@ -3875,7 +3897,7 @@ static int regulator_notifier(struct notifier_block *nb, if (event == REGULATOR_EVENT_PRE_DISABLE) qsmmuv2_halt(smmu); else if (event == REGULATOR_EVENT_ENABLE) { if (arm_smmu_restore_sec_cfg(smmu)) if (arm_smmu_restore_sec_cfg(smmu, 0)) goto power_off; qsmmuv2_resume(smmu); } Loading Loading @@ -4028,7 +4050,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) bool cttw_dt, cttw_reg; int i; if (arm_smmu_restore_sec_cfg(smmu)) if (arm_smmu_restore_sec_cfg(smmu, 0)) return -ENODEV; dev_dbg(smmu->dev, "probing hardware configuration...\n"); Loading include/soc/qcom/msm_tz_smmu.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -60,11 +60,16 @@ bool arm_smmu_skip_write(void __iomem *addr); /* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */ #undef writel_relaxed #undef writeq_relaxed #define writel_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writel((__force u32)cpu_to_le32(v), (c))); \ } while (0) #define writeq_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writeq((__force u64)cpu_to_le64(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 +31 −9 Original line number Diff line number Diff line Loading @@ -355,11 +355,13 @@ struct arm_smmu_s2cr { enum arm_smmu_s2cr_privcfg privcfg; u8 cbndx; bool cb_handoff; bool write_protected; }; #define s2cr_init_val (struct arm_smmu_s2cr){ \ .type = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS, \ .cb_handoff = false, \ .write_protected = false, \ } struct arm_smmu_smr { Loading Loading @@ -627,7 +629,7 @@ static bool is_dynamic_domain(struct iommu_domain *domain) return !!(smmu_domain->attributes & (1 << DOMAIN_ATTR_DYNAMIC)); } static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu) static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu, u32 cb) { int ret; int scm_ret = 0; Loading @@ -635,7 +637,7 @@ static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu) if (!arm_smmu_is_static_cb(smmu)) return 0; ret = scm_restore_sec_cfg(smmu->sec_id, 0x0, &scm_ret); ret = scm_restore_sec_cfg(smmu->sec_id, cb, &scm_ret); if (ret || scm_ret) { pr_err("scm call IOMMU_SECURE_CFG failed\n"); return -EINVAL; Loading Loading @@ -2758,14 +2760,29 @@ static struct arm_smmu_device *arm_smmu_get_by_addr(void __iomem *addr) bool arm_smmu_skip_write(void __iomem *addr) { struct arm_smmu_device *smmu; unsigned long cb; int i; smmu = arm_smmu_get_by_addr(addr); if (smmu && ((unsigned long)addr & (smmu->size - 1)) >= (smmu->size >> 1)) return false; else /* 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; for (i = 0; i < smmu->num_mapping_groups; i++) { if ((smmu->s2crs[i].cbndx == cb) && (smmu->s2crs[i].write_protected)) return true; } return false; } #endif static struct arm_smmu_device *arm_smmu_get_by_list(struct device_node *np) Loading Loading @@ -3698,9 +3715,14 @@ 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)) for_each_cfg_sme(fwspec, i, idx) smmu->s2crs[idx].write_protected = true; } 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 @@ -3875,7 +3897,7 @@ static int regulator_notifier(struct notifier_block *nb, if (event == REGULATOR_EVENT_PRE_DISABLE) qsmmuv2_halt(smmu); else if (event == REGULATOR_EVENT_ENABLE) { if (arm_smmu_restore_sec_cfg(smmu)) if (arm_smmu_restore_sec_cfg(smmu, 0)) goto power_off; qsmmuv2_resume(smmu); } Loading Loading @@ -4028,7 +4050,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) bool cttw_dt, cttw_reg; int i; if (arm_smmu_restore_sec_cfg(smmu)) if (arm_smmu_restore_sec_cfg(smmu, 0)) return -ENODEV; dev_dbg(smmu->dev, "probing hardware configuration...\n"); Loading
include/soc/qcom/msm_tz_smmu.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -60,11 +60,16 @@ bool arm_smmu_skip_write(void __iomem *addr); /* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */ #undef writel_relaxed #undef writeq_relaxed #define writel_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writel((__force u32)cpu_to_le32(v), (c))); \ } while (0) #define writeq_relaxed(v, c) do { \ if (!arm_smmu_skip_write(c)) \ ((void)__raw_writeq((__force u64)cpu_to_le64(v), (c))); \ } while (0) #else static inline int msm_tz_smmu_atos_start(struct device *dev, int cb_num) Loading