aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2016-08-25 07:52:51 -0400
committerJoerg Roedel <jroedel@suse.de>2016-09-05 07:00:28 -0400
commit1c5ebba95b486f1ea0e17d76dd8f6d7f1a8d1e89 (patch)
tree9514acd0448ff520f87ceaedf3eeff3e183aea50
parent76208356a0ab357a1fb9f43bedb7fd1046ad8ece (diff)
iommu/vt-d: Make sure RMRRs are mapped before domain goes public
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>
-rw-r--r--drivers/iommu/intel-iommu.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index bcdbe9de7560..a4407eabf0e6 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3428,17 +3428,18 @@ static unsigned long intel_alloc_iova(struct device *dev,
3428 3428
3429static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev) 3429static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
3430{ 3430{
3431 struct dmar_domain *domain, *tmp;
3431 struct dmar_rmrr_unit *rmrr; 3432 struct dmar_rmrr_unit *rmrr;
3432 struct dmar_domain *domain;
3433 struct device *i_dev; 3433 struct device *i_dev;
3434 int i, ret; 3434 int i, ret;
3435 3435
3436 domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH); 3436 domain = find_domain(dev);
3437 if (!domain) { 3437 if (domain)
3438 pr_err("Allocating domain for %s failed\n", 3438 goto out;
3439 dev_name(dev)); 3439
3440 return NULL; 3440 domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
3441 } 3441 if (!domain)
3442 goto out;
3442 3443
3443 /* We have a new domain - setup possible RMRRs for the device */ 3444 /* We have a new domain - setup possible RMRRs for the device */
3444 rcu_read_lock(); 3445 rcu_read_lock();
@@ -3457,6 +3458,18 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
3457 } 3458 }
3458 rcu_read_unlock(); 3459 rcu_read_unlock();
3459 3460
3461 tmp = set_domain_for_dev(dev, domain);
3462 if (!tmp || domain != tmp) {
3463 domain_exit(domain);
3464 domain = tmp;
3465 }
3466
3467out:
3468
3469 if (!domain)
3470 pr_err("Allocating domain for %s failed\n", dev_name(dev));
3471
3472
3460 return domain; 3473 return domain;
3461} 3474}
3462 3475