iommu/vt-d: Add blocking domain support
authorLu Baolu <baolu.lu@linux.intel.com>
Tue, 22 Nov 2022 00:29:45 +0000 (08:29 +0800)
committerJoerg Roedel <jroedel@suse.de>
Tue, 22 Nov 2022 13:05:21 +0000 (14:05 +0100)
The Intel IOMMU hardwares support blocking DMA transactions by clearing
the translation table entries. This implements a real blocking domain to
avoid using an empty UNMANAGED domain. The detach_dev callback of the
domain ops is not used in any path. Remove it to avoid dead code as well.

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/20221118132451.114406-4-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel/iommu.c

index 6aafb86..25c772e 100644 (file)
@@ -278,6 +278,7 @@ static LIST_HEAD(dmar_satc_units);
        list_for_each_entry(rmrr, &dmar_rmrr_units, list)
 
 static void device_block_translation(struct device *dev);
+static void intel_iommu_domain_free(struct iommu_domain *domain);
 
 int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
 int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
@@ -4162,12 +4163,28 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
        return 0;
 }
 
+static int blocking_domain_attach_dev(struct iommu_domain *domain,
+                                     struct device *dev)
+{
+       device_block_translation(dev);
+       return 0;
+}
+
+static struct iommu_domain blocking_domain = {
+       .ops = &(const struct iommu_domain_ops) {
+               .attach_dev     = blocking_domain_attach_dev,
+               .free           = intel_iommu_domain_free
+       }
+};
+
 static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
 {
        struct dmar_domain *dmar_domain;
        struct iommu_domain *domain;
 
        switch (type) {
+       case IOMMU_DOMAIN_BLOCKED:
+               return &blocking_domain;
        case IOMMU_DOMAIN_DMA:
        case IOMMU_DOMAIN_DMA_FQ:
        case IOMMU_DOMAIN_UNMANAGED:
@@ -4200,7 +4217,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
 
 static void intel_iommu_domain_free(struct iommu_domain *domain)
 {
-       if (domain != &si_domain->domain)
+       if (domain != &si_domain->domain && domain != &blocking_domain)
                domain_exit(to_dmar_domain(domain));
 }
 
@@ -4274,12 +4291,6 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
        return domain_add_dev_info(to_dmar_domain(domain), dev);
 }
 
-static void intel_iommu_detach_device(struct iommu_domain *domain,
-                                     struct device *dev)
-{
-       dmar_remove_one_dev_info(dev);
-}
-
 static int intel_iommu_map(struct iommu_domain *domain,
                           unsigned long iova, phys_addr_t hpa,
                           size_t size, int iommu_prot, gfp_t gfp)
@@ -4767,7 +4778,6 @@ const struct iommu_ops intel_iommu_ops = {
 #endif
        .default_domain_ops = &(const struct iommu_domain_ops) {
                .attach_dev             = intel_iommu_attach_device,
-               .detach_dev             = intel_iommu_detach_device,
                .map_pages              = intel_iommu_map_pages,
                .unmap_pages            = intel_iommu_unmap_pages,
                .iotlb_sync_map         = intel_iommu_iotlb_sync_map,