diff options
| author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-07-11 02:19:29 -0400 |
|---|---|---|
| committer | Joerg Roedel <jroedel@suse.de> | 2014-07-23 10:04:47 -0400 |
| commit | 44bde61428f7719c54a2074443edddf0e827296c (patch) | |
| tree | 0182bf0ceebd23310e8b95dba23218d10be63264 /drivers | |
| parent | fb170fb4c548c6d9fe9f71db946e216abb5c6641 (diff) | |
iommu/vt-d: Allocate dynamic domain id for virtual domains only
Check the same domain id is allocated for si_domain on each IOMMU,
otherwise the IOTLB flush for si_domain will fail.
Now the rules to allocate and manage domain id are:
1) For normal and static identity domains, domain id is allocated
when creating domain structure. And this id will be written into
context entry.
2) For virtual machine domain, a virtual id is allocated when creating
domain. And when binding virtual machine domain to an iommu, a real
domain id is allocated on demand and this domain id will be written
into context entry. So domain->id for virtual machine domain may be
different from the domain id written into context entry(used by
hardware).
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index eae9b0d8bc60..968e3d32e305 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -1549,15 +1549,27 @@ static int iommu_attach_domain(struct dmar_domain *domain, | |||
| 1549 | 1549 | ||
| 1550 | spin_lock_irqsave(&iommu->lock, flags); | 1550 | spin_lock_irqsave(&iommu->lock, flags); |
| 1551 | num = __iommu_attach_domain(domain, iommu); | 1551 | num = __iommu_attach_domain(domain, iommu); |
| 1552 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
| 1552 | if (num < 0) | 1553 | if (num < 0) |
| 1553 | pr_err("IOMMU: no free domain ids\n"); | 1554 | pr_err("IOMMU: no free domain ids\n"); |
| 1554 | else | ||
| 1555 | domain->id = num; | ||
| 1556 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
| 1557 | 1555 | ||
| 1558 | return num; | 1556 | return num; |
| 1559 | } | 1557 | } |
| 1560 | 1558 | ||
| 1559 | static int iommu_attach_vm_domain(struct dmar_domain *domain, | ||
| 1560 | struct intel_iommu *iommu) | ||
| 1561 | { | ||
| 1562 | int num; | ||
| 1563 | unsigned long ndomains; | ||
| 1564 | |||
| 1565 | ndomains = cap_ndoms(iommu->cap); | ||
| 1566 | for_each_set_bit(num, iommu->domain_ids, ndomains) | ||
| 1567 | if (iommu->domains[num] == domain) | ||
| 1568 | return num; | ||
| 1569 | |||
| 1570 | return __iommu_attach_domain(domain, iommu); | ||
| 1571 | } | ||
| 1572 | |||
| 1561 | static void iommu_detach_domain(struct dmar_domain *domain, | 1573 | static void iommu_detach_domain(struct dmar_domain *domain, |
| 1562 | struct intel_iommu *iommu) | 1574 | struct intel_iommu *iommu) |
| 1563 | { | 1575 | { |
| @@ -1764,8 +1776,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
| 1764 | struct context_entry *context; | 1776 | struct context_entry *context; |
| 1765 | unsigned long flags; | 1777 | unsigned long flags; |
| 1766 | struct dma_pte *pgd; | 1778 | struct dma_pte *pgd; |
| 1767 | unsigned long num; | ||
| 1768 | unsigned long ndomains; | ||
| 1769 | int id; | 1779 | int id; |
| 1770 | int agaw; | 1780 | int agaw; |
| 1771 | struct device_domain_info *info = NULL; | 1781 | struct device_domain_info *info = NULL; |
| @@ -1790,20 +1800,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
| 1790 | pgd = domain->pgd; | 1800 | pgd = domain->pgd; |
| 1791 | 1801 | ||
| 1792 | if (domain_type_is_vm_or_si(domain)) { | 1802 | if (domain_type_is_vm_or_si(domain)) { |
| 1793 | int found = 0; | 1803 | if (domain_type_is_vm(domain)) { |
| 1794 | 1804 | id = iommu_attach_vm_domain(domain, iommu); | |
| 1795 | /* find an available domain id for this device in iommu */ | ||
| 1796 | ndomains = cap_ndoms(iommu->cap); | ||
| 1797 | for_each_set_bit(num, iommu->domain_ids, ndomains) { | ||
| 1798 | if (iommu->domains[num] == domain) { | ||
| 1799 | id = num; | ||
| 1800 | found = 1; | ||
| 1801 | break; | ||
| 1802 | } | ||
| 1803 | } | ||
| 1804 | |||
| 1805 | if (found == 0) { | ||
| 1806 | id = __iommu_attach_domain(domain, iommu); | ||
| 1807 | if (id < 0) { | 1805 | if (id < 0) { |
| 1808 | spin_unlock_irqrestore(&iommu->lock, flags); | 1806 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 1809 | pr_err("IOMMU: no free domain ids\n"); | 1807 | pr_err("IOMMU: no free domain ids\n"); |
| @@ -2257,8 +2255,8 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw) | |||
| 2257 | domain = alloc_domain(0); | 2255 | domain = alloc_domain(0); |
| 2258 | if (!domain) | 2256 | if (!domain) |
| 2259 | return NULL; | 2257 | return NULL; |
| 2260 | 2258 | domain->id = iommu_attach_domain(domain, iommu); | |
| 2261 | if (iommu_attach_domain(domain, iommu) < 0) { | 2259 | if (domain->id < 0) { |
| 2262 | free_domain_mem(domain); | 2260 | free_domain_mem(domain); |
| 2263 | return NULL; | 2261 | return NULL; |
| 2264 | } | 2262 | } |
| @@ -2428,6 +2426,7 @@ static int __init si_domain_init(int hw) | |||
| 2428 | struct dmar_drhd_unit *drhd; | 2426 | struct dmar_drhd_unit *drhd; |
| 2429 | struct intel_iommu *iommu; | 2427 | struct intel_iommu *iommu; |
| 2430 | int nid, ret = 0; | 2428 | int nid, ret = 0; |
| 2429 | bool first = true; | ||
| 2431 | 2430 | ||
| 2432 | si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY); | 2431 | si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY); |
| 2433 | if (!si_domain) | 2432 | if (!si_domain) |
| @@ -2438,6 +2437,12 @@ static int __init si_domain_init(int hw) | |||
| 2438 | if (ret < 0) { | 2437 | if (ret < 0) { |
| 2439 | domain_exit(si_domain); | 2438 | domain_exit(si_domain); |
| 2440 | return -EFAULT; | 2439 | return -EFAULT; |
| 2440 | } else if (first) { | ||
| 2441 | si_domain->id = ret; | ||
| 2442 | first = false; | ||
| 2443 | } else if (si_domain->id != ret) { | ||
| 2444 | domain_exit(si_domain); | ||
| 2445 | return -EFAULT; | ||
| 2441 | } | 2446 | } |
| 2442 | domain_attach_iommu(si_domain, iommu); | 2447 | domain_attach_iommu(si_domain, iommu); |
| 2443 | } | 2448 | } |
