[Patch V2 2/2] iommu/arm-smmu: Fix race condition during iommu_group creation
From: Ashish Mhetre <hidden>
Date: 2021-06-17 20:31:32
Also in:
linux-iommu, lkml
Subsystem:
arm smmu drivers, iommu subsystem, the rest · Maintainers:
Will Deacon, Joerg Roedel, Linus Torvalds
From: Krishna Reddy <vdumpa@nvidia.com> iommu_group is getting created more than once during asynchronous multiple display heads(devices) probe on Tegra194 SoC. All the display heads share same SID and are expected to be in same iommu_group. As arm_smmu_device_group() is not protecting group creation across devices, it is leading to multiple groups creation across devices with same SID and subsequent IOMMU faults. During race, the iommu_probe_device() call for two display devices is ending up in arm_smmu_device_group() twice and hence two groups are getting created. Ideally after group creation for first display device, same group should be used by second display device. This race is leading to context faults when one display device is accessing IOVA from other display device which shouldn't be the case for devices sharing same SID. Fix this by protecting group creation with smmu->stream_map_mutex. Signed-off-by: Krishna Reddy <vdumpa@nvidia.com> --- Changes since V1: - Update the commit message per Will's suggestion drivers/iommu/arm/arm-smmu/arm-smmu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 6f72c4d..21af179 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c@@ -1458,6 +1458,7 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev) struct iommu_group *group = NULL; int i, idx; + mutex_lock(&smmu->stream_map_mutex); for_each_cfg_sme(cfg, fwspec, i, idx) { if (group && smmu->s2crs[idx].group && group != smmu->s2crs[idx].group)
@@ -1466,8 +1467,10 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev) group = smmu->s2crs[idx].group; } - if (group) + if (group) { + mutex_unlock(&smmu->stream_map_mutex); return iommu_group_ref_get(group); + } if (dev_is_pci(dev)) group = pci_device_group(dev);
@@ -1481,6 +1484,7 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev) for_each_cfg_sme(cfg, fwspec, i, idx) smmu->s2crs[idx].group = group; + mutex_unlock(&smmu->stream_map_mutex); return group; }
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel