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 <mitchelh@codeaurora.org>
This commit is contained in:
Mitchel Humpherys 2016-07-26 11:03:48 -07:00 committed by Liam Mark
parent 9e4b3ba4af
commit 6fbe4a9662

View file

@ -2820,10 +2820,16 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
struct iommu_group *group; struct iommu_group *group;
int ret; int ret;
if (dev_is_pci(dev)) /*
group = pci_device_group(dev); * We used to call pci_device_group here for dev_is_pci(dev)
else * devices. However, that causes the root complex device to be
group = generic_device_group(dev); * 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)) if (IS_ERR(group))
return group; return group;