diff options
author | Joerg Roedel <jroedel@suse.de> | 2016-08-25 07:52:51 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-09-05 07:00:28 -0400 |
commit | 1c5ebba95b486f1ea0e17d76dd8f6d7f1a8d1e89 (patch) | |
tree | 9514acd0448ff520f87ceaedf3eeff3e183aea50 | |
parent | 76208356a0ab357a1fb9f43bedb7fd1046ad8ece (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.c | 27 |
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 | ||
3429 | static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev) | 3429 | static 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 | |||
3467 | out: | ||
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 | ||