iommu/vt-d: Make sure RMRRs are mapped before domain goes public
authorJoerg Roedel <jroedel@suse.de>
Thu, 25 Aug 2016 11:52:51 +0000 (13:52 +0200)
committerJoerg Roedel <jroedel@suse.de>
Mon, 5 Sep 2016 11:00:28 +0000 (13:00 +0200)
When a domain is allocated through the get_valid_domain_for_dev
path, it will be context-mapped before the RMRR regions are
mapped in the page-table. This opens a short time window
where device-accesses to these regions fail and causing DMAR
faults.

Fix this by mapping the RMRR regions before the domain is
context-mapped.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel-iommu.c

index bcdbe9d..a4407ea 100644 (file)
@@ -3428,17 +3428,18 @@ static unsigned long intel_alloc_iova(struct device *dev,
 
 static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
 {
+       struct dmar_domain *domain, *tmp;
        struct dmar_rmrr_unit *rmrr;
-       struct dmar_domain *domain;
        struct device *i_dev;
        int i, ret;
 
-       domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
-       if (!domain) {
-               pr_err("Allocating domain for %s failed\n",
-                      dev_name(dev));
-               return NULL;
-       }
+       domain = find_domain(dev);
+       if (domain)
+               goto out;
+
+       domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+       if (!domain)
+               goto out;
 
        /* We have a new domain - setup possible RMRRs for the device */
        rcu_read_lock();
@@ -3457,6 +3458,18 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
        }
        rcu_read_unlock();
 
+       tmp = set_domain_for_dev(dev, domain);
+       if (!tmp || domain != tmp) {
+               domain_exit(domain);
+               domain = tmp;
+       }
+
+out:
+
+       if (!domain)
+               pr_err("Allocating domain for %s failed\n", dev_name(dev));
+
+
        return domain;
 }