From 6fbe4a9662e808bf381a834d85c4b5e08f9241df Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Tue, 26 Jul 2016 11:03:48 -0700 Subject: [PATCH] iommu/arm-smmu: Don't group PCI devices In general, the IOMMU framework likes to group PCI devices together. This prevents someone from assigning them to separate VMs using VFIO, for example. The reason they shouldn't go to separate VMs is because there could be DMA aliasing between endpoint devices, and because the root complex device can access anything that endpoint devices can access. Unfortunately, this makes things difficult in the DMA layer since the IOMMU framework freaks out if you try to attach a single device that is also part of a group. First instinct might be to start using iommu_attach_group instead of iommu_attach_device in the DMA layer but that has problems of its own (it attaches *everyone* in the group as soon as one client attaches). Besides all that, it's also a bit annoying to have the root complex device in group since, in our platform, it doesn't actually have any stream IDs assigned to it and it doesn't do any DMA of its own, so it doesn't really make any logical sense to attach it. As a compromise, we can stop grouping PCI devices together by allocating a new domain for each one. By doing so we no longer need to call iommu_attach_group in the DMA layer, avoid the issues described above. It should be noted that with this patch in place we can't securely do any direct DMA assignment of PCI endpoint devices to separate VMs. CRs-Fixed: 1036401 Change-Id: I9528b61a695dc7840e1c6f80af18044340f5c6c4 Signed-off-by: Mitchel Humpherys --- drivers/iommu/arm-smmu.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index ce3f8713df3e..0f32945d2df8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2820,10 +2820,16 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev) struct iommu_group *group; int ret; - if (dev_is_pci(dev)) - group = pci_device_group(dev); - else - group = generic_device_group(dev); + /* + * We used to call pci_device_group here for dev_is_pci(dev) + * devices. However, that causes the root complex device to be + * placed in the same group as endpoint devices (and probably puts + * all endpoint devices in the same group as well), which makes + * things tricky in the DMA layer since we don't actually want to + * attach *everybody* in the group when one client calls attach. + * Instead, we'll just allocate a new group for everybody here. + */ + group = generic_device_group(dev); if (IS_ERR(group)) return group; -- 2.11.0