iommu/vt-d: Check device list of domain in domain free path
authorLu Baolu <baolu.lu@linux.intel.com>
Tue, 12 Jul 2022 00:08:59 +0000 (08:08 +0800)
committerJoerg Roedel <jroedel@suse.de>
Fri, 15 Jul 2022 08:21:38 +0000 (10:21 +0200)
When the IOMMU domain is about to be freed, it should not be set on any
device. Instead of silently dealing with some bug cases, it's better to
trigger a warning to report and fix any potential bugs at the first time.

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

index 3d53de8..a94fb69 100644 (file)
@@ -294,7 +294,6 @@ static LIST_HEAD(dmar_satc_units);
 /* bitmap for indexing intel_iommus */
 static int g_num_of_iommus;
 
-static void domain_remove_dev_info(struct dmar_domain *domain);
 static void dmar_remove_one_dev_info(struct device *dev);
 static void __dmar_remove_one_dev_info(struct device_domain_info *info);
 
@@ -1841,10 +1840,6 @@ static inline int guestwidth_to_adjustwidth(int gaw)
 
 static void domain_exit(struct dmar_domain *domain)
 {
-
-       /* Remove associated devices and clear attached or cached domains */
-       domain_remove_dev_info(domain);
-
        if (domain->pgd) {
                LIST_HEAD(freelist);
 
@@ -1852,6 +1847,9 @@ static void domain_exit(struct dmar_domain *domain)
                put_pages_list(&freelist);
        }
 
+       if (WARN_ON(!list_empty(&domain->devices)))
+               return;
+
        kfree(domain);
 }
 
@@ -2333,16 +2331,6 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
        __iommu_flush_dev_iotlb(info, 0, MAX_AGAW_PFN_WIDTH);
 }
 
-static void domain_remove_dev_info(struct dmar_domain *domain)
-{
-       struct device_domain_info *info, *tmp;
-
-       spin_lock(&device_domain_lock);
-       list_for_each_entry_safe(info, tmp, &domain->devices, link)
-               __dmar_remove_one_dev_info(info);
-       spin_unlock(&device_domain_lock);
-}
-
 static int domain_setup_first_level(struct intel_iommu *iommu,
                                    struct dmar_domain *domain,
                                    struct device *dev,