aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-09-12 12:13:54 -0400
committerWill Deacon <will.deacon@arm.com>2016-09-16 04:34:20 -0400
commit588888a7399db352d2b1a41c9d5b3bf0fd482390 (patch)
treeae2e5e9ef4848d72794beaba0360591bed717dde /drivers/iommu/arm-smmu.c
parentd3097e39302083d58922a3d1032d7d59a63d263d (diff)
iommu/arm-smmu: Intelligent SMR allocation
Stream Match Registers are one of the more awkward parts of the SMMUv2 architecture; there are typically never enough to assign one to each stream ID in the system, and configuring them such that a single ID matches multiple entries is catastrophically bad - at best, every transaction raises a global fault; at worst, they go *somewhere*. To address the former issue, we can mask ID bits such that a single register may be used to match multiple IDs belonging to the same device or group, but doing so also heightens the risk of the latter problem (which can be nasty to debug). Tackle both problems at once by replacing the simple bitmap allocator with something much cleverer. Now that we have convenient in-memory representations of the stream mapping table, it becomes straightforward to properly validate new SMR entries against the current state, opening the door to arbitrary masking and SMR sharing. Another feature which falls out of this is that with IDs shared by separate devices being automatically accounted for, simply associating a group pointer with the S2CR offers appropriate group allocation almost for free, so hook that up in the process. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c197
1 files changed, 119 insertions, 78 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index f402f9e126a8..7a2bd60a54da 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -302,6 +302,8 @@ enum arm_smmu_implementation {
302}; 302};
303 303
304struct arm_smmu_s2cr { 304struct arm_smmu_s2cr {
305 struct iommu_group *group;
306 int count;
305 enum arm_smmu_s2cr_type type; 307 enum arm_smmu_s2cr_type type;
306 enum arm_smmu_s2cr_privcfg privcfg; 308 enum arm_smmu_s2cr_privcfg privcfg;
307 u8 cbndx; 309 u8 cbndx;
@@ -363,6 +365,7 @@ struct arm_smmu_device {
363 u16 smr_mask_mask; 365 u16 smr_mask_mask;
364 struct arm_smmu_smr *smrs; 366 struct arm_smmu_smr *smrs;
365 struct arm_smmu_s2cr *s2crs; 367 struct arm_smmu_s2cr *s2crs;
368 struct mutex stream_map_mutex;
366 369
367 unsigned long va_size; 370 unsigned long va_size;
368 unsigned long ipa_size; 371 unsigned long ipa_size;
@@ -1041,23 +1044,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
1041 kfree(smmu_domain); 1044 kfree(smmu_domain);
1042} 1045}
1043 1046
1044static int arm_smmu_alloc_smr(struct arm_smmu_device *smmu)
1045{
1046 int i;
1047
1048 for (i = 0; i < smmu->num_mapping_groups; i++)
1049 if (!cmpxchg(&smmu->smrs[i].valid, false, true))
1050 return i;
1051
1052 return INVALID_SMENDX;
1053}
1054
1055static void arm_smmu_free_smr(struct arm_smmu_device *smmu, int idx)
1056{
1057 writel_relaxed(~SMR_VALID, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
1058 WRITE_ONCE(smmu->smrs[idx].valid, false);
1059}
1060
1061static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx) 1047static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
1062{ 1048{
1063 struct arm_smmu_smr *smr = smmu->smrs + idx; 1049 struct arm_smmu_smr *smr = smmu->smrs + idx;
@@ -1085,49 +1071,115 @@ static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
1085 arm_smmu_write_smr(smmu, idx); 1071 arm_smmu_write_smr(smmu, idx);
1086} 1072}
1087 1073
1088static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu, 1074static int arm_smmu_find_sme(struct arm_smmu_device *smmu, u16 id, u16 mask)
1089 struct arm_smmu_master_cfg *cfg)
1090{ 1075{
1091 struct arm_smmu_smr *smrs = smmu->smrs; 1076 struct arm_smmu_smr *smrs = smmu->smrs;
1092 int i, idx; 1077 int i, free_idx = -ENOSPC;
1093
1094 /* Allocate the SMRs on the SMMU */
1095 for_each_cfg_sme(cfg, i, idx) {
1096 if (idx != INVALID_SMENDX)
1097 return -EEXIST;
1098 1078
1099 /* ...except on stream indexing hardware, of course */ 1079 /* Stream indexing is blissfully easy */
1100 if (!smrs) { 1080 if (!smrs)
1101 cfg->smendx[i] = cfg->streamids[i]; 1081 return id;
1082
1083 /* Validating SMRs is... less so */
1084 for (i = 0; i < smmu->num_mapping_groups; ++i) {
1085 if (!smrs[i].valid) {
1086 /*
1087 * Note the first free entry we come across, which
1088 * we'll claim in the end if nothing else matches.
1089 */
1090 if (free_idx < 0)
1091 free_idx = i;
1102 continue; 1092 continue;
1103 } 1093 }
1094 /*
1095 * If the new entry is _entirely_ matched by an existing entry,
1096 * then reuse that, with the guarantee that there also cannot
1097 * be any subsequent conflicting entries. In normal use we'd
1098 * expect simply identical entries for this case, but there's
1099 * no harm in accommodating the generalisation.
1100 */
1101 if ((mask & smrs[i].mask) == mask &&
1102 !((id ^ smrs[i].id) & ~smrs[i].mask))
1103 return i;
1104 /*
1105 * If the new entry has any other overlap with an existing one,
1106 * though, then there always exists at least one stream ID
1107 * which would cause a conflict, and we can't allow that risk.
1108 */
1109 if (!((id ^ smrs[i].id) & ~(smrs[i].mask | mask)))
1110 return -EINVAL;
1111 }
1104 1112
1105 idx = arm_smmu_alloc_smr(smmu); 1113 return free_idx;
1106 if (idx < 0) { 1114}
1107 dev_err(smmu->dev, "failed to allocate free SMR\n"); 1115
1108 goto err_free_smrs; 1116static bool arm_smmu_free_sme(struct arm_smmu_device *smmu, int idx)
1117{
1118 if (--smmu->s2crs[idx].count)
1119 return false;
1120
1121 smmu->s2crs[idx] = s2cr_init_val;
1122 if (smmu->smrs)
1123 smmu->smrs[idx].valid = false;
1124
1125 return true;
1126}
1127
1128static int arm_smmu_master_alloc_smes(struct device *dev)
1129{
1130 struct arm_smmu_master_cfg *cfg = dev->archdata.iommu;
1131 struct arm_smmu_device *smmu = cfg->smmu;
1132 struct arm_smmu_smr *smrs = smmu->smrs;
1133 struct iommu_group *group;
1134 int i, idx, ret;
1135
1136 mutex_lock(&smmu->stream_map_mutex);
1137 /* Figure out a viable stream map entry allocation */
1138 for_each_cfg_sme(cfg, i, idx) {
1139 if (idx != INVALID_SMENDX) {
1140 ret = -EEXIST;
1141 goto out_err;
1109 } 1142 }
1110 cfg->smendx[i] = idx;
1111 1143
1112 smrs[idx].id = cfg->streamids[i]; 1144 ret = arm_smmu_find_sme(smmu, cfg->streamids[i], 0);
1113 smrs[idx].mask = 0; /* We don't currently share SMRs */ 1145 if (ret < 0)
1146 goto out_err;
1147
1148 idx = ret;
1149 if (smrs && smmu->s2crs[idx].count == 0) {
1150 smrs[idx].id = cfg->streamids[i];
1151 smrs[idx].mask = 0; /* We don't currently share SMRs */
1152 smrs[idx].valid = true;
1153 }
1154 smmu->s2crs[idx].count++;
1155 cfg->smendx[i] = (s16)idx;
1114 } 1156 }
1115 1157
1116 if (!smrs) 1158 group = iommu_group_get_for_dev(dev);
1117 return 0; 1159 if (!group)
1160 group = ERR_PTR(-ENOMEM);
1161 if (IS_ERR(group)) {
1162 ret = PTR_ERR(group);
1163 goto out_err;
1164 }
1165 iommu_group_put(group);
1118 1166
1119 /* It worked! Now, poke the actual hardware */ 1167 /* It worked! Now, poke the actual hardware */
1120 for_each_cfg_sme(cfg, i, idx) 1168 for_each_cfg_sme(cfg, i, idx) {
1121 arm_smmu_write_smr(smmu, idx); 1169 arm_smmu_write_sme(smmu, idx);
1170 smmu->s2crs[idx].group = group;
1171 }
1122 1172
1173 mutex_unlock(&smmu->stream_map_mutex);
1123 return 0; 1174 return 0;
1124 1175
1125err_free_smrs: 1176out_err:
1126 while (i--) { 1177 while (i--) {
1127 arm_smmu_free_smr(smmu, cfg->smendx[i]); 1178 arm_smmu_free_sme(smmu, cfg->smendx[i]);
1128 cfg->smendx[i] = INVALID_SMENDX; 1179 cfg->smendx[i] = INVALID_SMENDX;
1129 } 1180 }
1130 return -ENOSPC; 1181 mutex_unlock(&smmu->stream_map_mutex);
1182 return ret;
1131} 1183}
1132 1184
1133static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg) 1185static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg)
@@ -1135,43 +1187,23 @@ static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg)
1135 struct arm_smmu_device *smmu = cfg->smmu; 1187 struct arm_smmu_device *smmu = cfg->smmu;
1136 int i, idx; 1188 int i, idx;
1137 1189
1138 /* 1190 mutex_lock(&smmu->stream_map_mutex);
1139 * We *must* clear the S2CR first, because freeing the SMR means
1140 * that it can be re-allocated immediately.
1141 */
1142 for_each_cfg_sme(cfg, i, idx) { 1191 for_each_cfg_sme(cfg, i, idx) {
1143 /* An IOMMU group is torn down by the first device to be removed */ 1192 if (arm_smmu_free_sme(smmu, idx))
1144 if (idx == INVALID_SMENDX) 1193 arm_smmu_write_sme(smmu, idx);
1145 return;
1146
1147 smmu->s2crs[idx] = s2cr_init_val;
1148 arm_smmu_write_s2cr(smmu, idx);
1149 }
1150 /* Sync S2CR updates before touching anything else */
1151 __iowmb();
1152
1153 /* Invalidate the SMRs before freeing back to the allocator */
1154 for_each_cfg_sme(cfg, i, idx) {
1155 if (smmu->smrs)
1156 arm_smmu_free_smr(smmu, idx);
1157
1158 cfg->smendx[i] = INVALID_SMENDX; 1194 cfg->smendx[i] = INVALID_SMENDX;
1159 } 1195 }
1196 mutex_unlock(&smmu->stream_map_mutex);
1160} 1197}
1161 1198
1162static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, 1199static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1163 struct arm_smmu_master_cfg *cfg) 1200 struct arm_smmu_master_cfg *cfg)
1164{ 1201{
1165 int i, idx, ret = 0;
1166 struct arm_smmu_device *smmu = smmu_domain->smmu; 1202 struct arm_smmu_device *smmu = smmu_domain->smmu;
1167 struct arm_smmu_s2cr *s2cr = smmu->s2crs; 1203 struct arm_smmu_s2cr *s2cr = smmu->s2crs;
1168 enum arm_smmu_s2cr_type type = S2CR_TYPE_TRANS; 1204 enum arm_smmu_s2cr_type type = S2CR_TYPE_TRANS;
1169 u8 cbndx = smmu_domain->cfg.cbndx; 1205 u8 cbndx = smmu_domain->cfg.cbndx;
1170 1206 int i, idx;
1171 if (cfg->smendx[0] == INVALID_SMENDX)
1172 ret = arm_smmu_master_alloc_smes(smmu, cfg);
1173 if (ret)
1174 return ret;
1175 1207
1176 /* 1208 /*
1177 * FIXME: This won't be needed once we have IOMMU-backed DMA ops 1209 * FIXME: This won't be needed once we have IOMMU-backed DMA ops
@@ -1183,9 +1215,8 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1183 type = S2CR_TYPE_BYPASS; 1215 type = S2CR_TYPE_BYPASS;
1184 1216
1185 for_each_cfg_sme(cfg, i, idx) { 1217 for_each_cfg_sme(cfg, i, idx) {
1186 /* Devices in an IOMMU group may already be configured */
1187 if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx) 1218 if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx)
1188 break; 1219 continue;
1189 1220
1190 s2cr[idx].type = type; 1221 s2cr[idx].type = type;
1191 s2cr[idx].privcfg = S2CR_PRIVCFG_UNPRIV; 1222 s2cr[idx].privcfg = S2CR_PRIVCFG_UNPRIV;
@@ -1345,7 +1376,6 @@ static bool arm_smmu_capable(enum iommu_cap cap)
1345static int arm_smmu_add_device(struct device *dev) 1376static int arm_smmu_add_device(struct device *dev)
1346{ 1377{
1347 struct arm_smmu_master_cfg *cfg; 1378 struct arm_smmu_master_cfg *cfg;
1348 struct iommu_group *group;
1349 int i, ret; 1379 int i, ret;
1350 1380
1351 ret = arm_smmu_register_legacy_master(dev); 1381 ret = arm_smmu_register_legacy_master(dev);
@@ -1365,13 +1395,9 @@ static int arm_smmu_add_device(struct device *dev)
1365 cfg->smendx[i] = INVALID_SMENDX; 1395 cfg->smendx[i] = INVALID_SMENDX;
1366 } 1396 }
1367 1397
1368 group = iommu_group_get_for_dev(dev); 1398 ret = arm_smmu_master_alloc_smes(dev);
1369 if (IS_ERR(group)) { 1399 if (!ret)
1370 ret = PTR_ERR(group); 1400 return ret;
1371 goto out_free;
1372 }
1373 iommu_group_put(group);
1374 return 0;
1375 1401
1376out_free: 1402out_free:
1377 kfree(cfg); 1403 kfree(cfg);
@@ -1394,7 +1420,21 @@ static void arm_smmu_remove_device(struct device *dev)
1394 1420
1395static struct iommu_group *arm_smmu_device_group(struct device *dev) 1421static struct iommu_group *arm_smmu_device_group(struct device *dev)
1396{ 1422{
1397 struct iommu_group *group; 1423 struct arm_smmu_master_cfg *cfg = dev->archdata.iommu;
1424 struct arm_smmu_device *smmu = cfg->smmu;
1425 struct iommu_group *group = NULL;
1426 int i, idx;
1427
1428 for_each_cfg_sme(cfg, i, idx) {
1429 if (group && smmu->s2crs[idx].group &&
1430 group != smmu->s2crs[idx].group)
1431 return ERR_PTR(-EINVAL);
1432
1433 group = smmu->s2crs[idx].group;
1434 }
1435
1436 if (group)
1437 return group;
1398 1438
1399 if (dev_is_pci(dev)) 1439 if (dev_is_pci(dev))
1400 group = pci_device_group(dev); 1440 group = pci_device_group(dev);
@@ -1677,6 +1717,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1677 smmu->s2crs[i] = s2cr_init_val; 1717 smmu->s2crs[i] = s2cr_init_val;
1678 1718
1679 smmu->num_mapping_groups = size; 1719 smmu->num_mapping_groups = size;
1720 mutex_init(&smmu->stream_map_mutex);
1680 1721
1681 if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) { 1722 if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) {
1682 smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L; 1723 smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L;