Skip to content

Commit 8038bdb

Browse files
Jon Derrickjoergroedel
authored andcommitted
iommu/vt-d: Only clear real DMA device's context entries
Domain context mapping can encounter issues with sub-devices of a real DMA device. A sub-device cannot have a valid context entry due to it potentially aliasing another device's 16-bit ID. It's expected that sub-devices of the real DMA device uses the real DMA device's requester when context mapping. This is an issue when a sub-device is removed where the context entry is cleared for all aliases. Other sub-devices are still valid, resulting in those sub-devices being stranded without valid context entries. The correct approach is to use the real DMA device when programming the context entries. The insertion path is correct because device_to_iommu() will return the bus and devfn of the real DMA device. The removal path needs to only operate on the real DMA device, otherwise the entire context entry would be cleared for all sub-devices of the real DMA device. This patch also adds a helper to determine if a struct device is a sub-device of a real DMA device. Fixes: 2b0140c ("iommu/vt-d: Use pci_real_dma_dev() for mapping") Cc: [email protected] # v5.6+ Signed-off-by: Jon Derrick <[email protected]> Acked-by: Lu Baolu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 7809c4d commit 8038bdb

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2500,6 +2500,12 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
25002500
flags);
25012501
}
25022502

2503+
static bool dev_is_real_dma_subdevice(struct device *dev)
2504+
{
2505+
return dev && dev_is_pci(dev) &&
2506+
pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev);
2507+
}
2508+
25032509
static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
25042510
int bus, int devfn,
25052511
struct device *dev,
@@ -4975,7 +4981,8 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
49754981
PASID_RID2PASID, false);
49764982

49774983
iommu_disable_dev_iotlb(info);
4978-
domain_context_clear(iommu, info->dev);
4984+
if (!dev_is_real_dma_subdevice(info->dev))
4985+
domain_context_clear(iommu, info->dev);
49794986
intel_pasid_free_table(info->dev);
49804987
}
49814988

0 commit comments

Comments
 (0)