The PCI devices handled by intel-iommu may have a DMA requester on another bus, such as VMD subdevices needing to use the VMD endpoint.
The real DMA device is now used for the DMA mapping, but one case was missed earlier, when allocating memory through (e.g.) intel_map_page(). Confusion ensues if the iommu domain type for the subdevice does not match the iommu domain type for the real DMA device. For example, take the case of the subdevice handled by intel_map_page() in a IOMMU_DOMAIN_DMA, with the real DMA device in a IOMMU_DOMAIN_IDENTITY: 1. intel_map_page() checks if an IOMMU mapping is needed by calling iommu_need_mapping() on the subdevice. Result: mapping is needed. 2. __intel_map_single() is called to create the mapping: - __intel_map_single() calls find_domain(). This function now returns the IDENTITY domain corresponding to the real DMA device. - __intel_map_single() then calls domain_get_iommu() on this "real" domain. A failure is hit and the entire operation is aborted, because this codepath is not intended to handle IDENTITY mappings: if (WARN_ON(domain->domain.type != IOMMU_DOMAIN_DMA)) return NULL; Fix this by using the real DMA device when checking if a mapping is needed. The above case will then directly fall back on dma_direct_map_page(). Fixes: 2b0140c69637 ("iommu/vt-d: Use pci_real_dma_dev() for mapping") Signed-off-by: Daniel Drake <dr...@endlessm.com> --- Notes: This problem was detected with a non-upstream patch "PCI: Add Intel remapped NVMe device support" (https://marc.info/?l=linux-ide&m=156015271021615&w=2) This patch creates PCI devices in the same way as VMD, and hence I believe VMD would hit this class of problem for any cases where iommu domain type may mismatch between subdevice and real device, which we have run into here. However this hasn't actually been tested on VMD (don't have the hardware) so if I've missed anything and/or it's not a real issue then feel free to drop this patch. drivers/iommu/intel-iommu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 9dc37672bf89..713810f8350c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3587,6 +3587,9 @@ static bool iommu_need_mapping(struct device *dev) if (iommu_dummy(dev)) return false; + if (dev_is_pci(dev)) + dev = &pci_real_dma_dev(to_pci_dev(dev))->dev; + ret = identity_mapping(dev); if (ret) { u64 dma_mask = *dev->dma_mask; -- 2.20.1 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu