summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorLu Baolu <baolu.lu@linux.intel.com>2019-05-25 01:41:30 -0400
committerJoerg Roedel <jroedel@suse.de>2019-05-28 04:19:10 -0400
commit98b2fffb5e274d73e47d495da2caf213cfa28fc8 (patch)
tree0bee16b84eed0634da7d6d1270d09c3680c5db1d /drivers/iommu/intel-iommu.c
parent942067f1b6b97b1e97cd073b0e2815bc499656db (diff)
iommu/vt-d: Handle 32bit device with identity default domain
The iommu driver doesn't know whether the bit width of a PCI device is sufficient for access to the whole system memory. Hence, the driver checks this when the driver calls into the dma APIs. If a device is using an identity domain, but the bit width is less than the system requirement, we need to use a dma domain instead. This also applies after we delegated the domain life cycle management to the upper layer. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r--drivers/iommu/intel-iommu.c55
1 files changed, 22 insertions, 33 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 5dae957531f3..87f9f2237238 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2984,25 +2984,6 @@ static int device_def_domain_type(struct device *dev, int startup)
2984 return IOMMU_DOMAIN_DMA; 2984 return IOMMU_DOMAIN_DMA;
2985 } 2985 }
2986 2986
2987 /*
2988 * At boot time, we don't yet know if devices will be 64-bit capable.
2989 * Assume that they will — if they turn out not to be, then we can
2990 * take them out of the 1:1 domain later.
2991 */
2992 if (!startup) {
2993 /*
2994 * If the device's dma_mask is less than the system's memory
2995 * size then this is not a candidate for identity mapping.
2996 */
2997 u64 dma_mask = *dev->dma_mask;
2998
2999 if (dev->coherent_dma_mask &&
3000 dev->coherent_dma_mask < dma_mask)
3001 dma_mask = dev->coherent_dma_mask;
3002
3003 return dma_mask >= dma_get_required_mask(dev);
3004 }
3005
3006 return (iommu_identity_mapping & IDENTMAP_ALL) ? 2987 return (iommu_identity_mapping & IDENTMAP_ALL) ?
3007 IOMMU_DOMAIN_IDENTITY : 0; 2988 IOMMU_DOMAIN_IDENTITY : 0;
3008} 2989}
@@ -3614,14 +3595,19 @@ out:
3614/* Check if the dev needs to go through non-identity map and unmap process.*/ 3595/* Check if the dev needs to go through non-identity map and unmap process.*/
3615static bool iommu_need_mapping(struct device *dev) 3596static bool iommu_need_mapping(struct device *dev)
3616{ 3597{
3617 int found; 3598 int ret;
3618 3599
3619 if (iommu_dummy(dev)) 3600 if (iommu_dummy(dev))
3620 return false; 3601 return false;
3621 3602
3622 found = identity_mapping(dev); 3603 ret = identity_mapping(dev);
3623 if (found) { 3604 if (ret) {
3624 if (iommu_should_identity_map(dev, 0)) 3605 u64 dma_mask = *dev->dma_mask;
3606
3607 if (dev->coherent_dma_mask && dev->coherent_dma_mask < dma_mask)
3608 dma_mask = dev->coherent_dma_mask;
3609
3610 if (dma_mask >= dma_get_required_mask(dev))
3625 return false; 3611 return false;
3626 3612
3627 /* 3613 /*
@@ -3629,17 +3615,20 @@ static bool iommu_need_mapping(struct device *dev)
3629 * non-identity mapping. 3615 * non-identity mapping.
3630 */ 3616 */
3631 dmar_remove_one_dev_info(dev); 3617 dmar_remove_one_dev_info(dev);
3632 dev_info(dev, "32bit DMA uses non-identity mapping\n"); 3618 ret = iommu_request_dma_domain_for_dev(dev);
3633 } else { 3619 if (ret) {
3634 /* 3620 struct iommu_domain *domain;
3635 * In case of a detached 64 bit DMA device from vm, the device 3621 struct dmar_domain *dmar_domain;
3636 * is put into si_domain for identity mapping. 3622
3637 */ 3623 domain = iommu_get_domain_for_dev(dev);
3638 if (iommu_should_identity_map(dev, 0) && 3624 if (domain) {
3639 !domain_add_dev_info(si_domain, dev)) { 3625 dmar_domain = to_dmar_domain(domain);
3640 dev_info(dev, "64bit DMA uses identity mapping\n"); 3626 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
3641 return false; 3627 }
3628 get_valid_domain_for_dev(dev);
3642 } 3629 }
3630
3631 dev_info(dev, "32bit DMA uses non-identity mapping\n");
3643 } 3632 }
3644 3633
3645 return true; 3634 return true;