diff options
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 59 |
1 files changed, 26 insertions, 33 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d77009bdade5..52250b3e58d1 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -320,16 +320,13 @@ static inline int first_pte_in_page(struct dma_pte *pte) | |||
| 320 | static struct dmar_domain *si_domain; | 320 | static struct dmar_domain *si_domain; |
| 321 | static int hw_pass_through = 1; | 321 | static int hw_pass_through = 1; |
| 322 | 322 | ||
| 323 | /* devices under the same p2p bridge are owned in one domain */ | ||
| 324 | #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0) | ||
| 325 | |||
| 326 | /* domain represents a virtual machine, more than one devices | 323 | /* domain represents a virtual machine, more than one devices |
| 327 | * across iommus may be owned in one domain, e.g. kvm guest. | 324 | * across iommus may be owned in one domain, e.g. kvm guest. |
| 328 | */ | 325 | */ |
| 329 | #define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 1) | 326 | #define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0) |
| 330 | 327 | ||
| 331 | /* si_domain contains mulitple devices */ | 328 | /* si_domain contains mulitple devices */ |
| 332 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2) | 329 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1) |
| 333 | 330 | ||
| 334 | /* define the limit of IOMMUs supported in each domain */ | 331 | /* define the limit of IOMMUs supported in each domain */ |
| 335 | #ifdef CONFIG_X86 | 332 | #ifdef CONFIG_X86 |
| @@ -539,6 +536,16 @@ void free_iova_mem(struct iova *iova) | |||
| 539 | kmem_cache_free(iommu_iova_cache, iova); | 536 | kmem_cache_free(iommu_iova_cache, iova); |
| 540 | } | 537 | } |
| 541 | 538 | ||
| 539 | static inline int domain_type_is_vm(struct dmar_domain *domain) | ||
| 540 | { | ||
| 541 | return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE; | ||
| 542 | } | ||
| 543 | |||
| 544 | static inline int domain_type_is_vm_or_si(struct dmar_domain *domain) | ||
| 545 | { | ||
| 546 | return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE | | ||
| 547 | DOMAIN_FLAG_STATIC_IDENTITY); | ||
| 548 | } | ||
| 542 | 549 | ||
| 543 | static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) | 550 | static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) |
| 544 | { | 551 | { |
| @@ -579,9 +586,7 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) | |||
| 579 | int iommu_id; | 586 | int iommu_id; |
| 580 | 587 | ||
| 581 | /* si_domain and vm domain should not get here. */ | 588 | /* si_domain and vm domain should not get here. */ |
| 582 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); | 589 | BUG_ON(domain_type_is_vm_or_si(domain)); |
| 583 | BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY); | ||
| 584 | |||
| 585 | iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus); | 590 | iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus); |
| 586 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) | 591 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) |
| 587 | return NULL; | 592 | return NULL; |
| @@ -1497,7 +1502,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu) | |||
| 1497 | free_context_table(iommu); | 1502 | free_context_table(iommu); |
| 1498 | } | 1503 | } |
| 1499 | 1504 | ||
| 1500 | static struct dmar_domain *alloc_domain(bool vm) | 1505 | static struct dmar_domain *alloc_domain(int flags) |
| 1501 | { | 1506 | { |
| 1502 | /* domain id for virtual machine, it won't be set in context */ | 1507 | /* domain id for virtual machine, it won't be set in context */ |
| 1503 | static atomic_t vm_domid = ATOMIC_INIT(0); | 1508 | static atomic_t vm_domid = ATOMIC_INIT(0); |
| @@ -1507,16 +1512,13 @@ static struct dmar_domain *alloc_domain(bool vm) | |||
| 1507 | if (!domain) | 1512 | if (!domain) |
| 1508 | return NULL; | 1513 | return NULL; |
| 1509 | 1514 | ||
| 1515 | memset(domain, 0, sizeof(*domain)); | ||
| 1510 | domain->nid = -1; | 1516 | domain->nid = -1; |
| 1511 | domain->iommu_count = 0; | 1517 | domain->flags = flags; |
| 1512 | memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp)); | ||
| 1513 | domain->flags = 0; | ||
| 1514 | spin_lock_init(&domain->iommu_lock); | 1518 | spin_lock_init(&domain->iommu_lock); |
| 1515 | INIT_LIST_HEAD(&domain->devices); | 1519 | INIT_LIST_HEAD(&domain->devices); |
| 1516 | if (vm) { | 1520 | if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE) |
| 1517 | domain->id = atomic_inc_return(&vm_domid); | 1521 | domain->id = atomic_inc_return(&vm_domid); |
| 1518 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; | ||
| 1519 | } | ||
| 1520 | 1522 | ||
| 1521 | return domain; | 1523 | return domain; |
| 1522 | } | 1524 | } |
| @@ -1704,7 +1706,7 @@ static void domain_exit(struct dmar_domain *domain) | |||
| 1704 | /* clear attached or cached domains */ | 1706 | /* clear attached or cached domains */ |
| 1705 | rcu_read_lock(); | 1707 | rcu_read_lock(); |
| 1706 | for_each_active_iommu(iommu, drhd) | 1708 | for_each_active_iommu(iommu, drhd) |
| 1707 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE || | 1709 | if (domain_type_is_vm(domain) || |
| 1708 | test_bit(iommu->seq_id, domain->iommu_bmp)) | 1710 | test_bit(iommu->seq_id, domain->iommu_bmp)) |
| 1709 | iommu_detach_domain(domain, iommu); | 1711 | iommu_detach_domain(domain, iommu); |
| 1710 | rcu_read_unlock(); | 1712 | rcu_read_unlock(); |
| @@ -1746,8 +1748,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
| 1746 | id = domain->id; | 1748 | id = domain->id; |
| 1747 | pgd = domain->pgd; | 1749 | pgd = domain->pgd; |
| 1748 | 1750 | ||
| 1749 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE || | 1751 | if (domain_type_is_vm_or_si(domain)) { |
| 1750 | domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) { | ||
| 1751 | int found = 0; | 1752 | int found = 0; |
| 1752 | 1753 | ||
| 1753 | /* find an available domain id for this device in iommu */ | 1754 | /* find an available domain id for this device in iommu */ |
| @@ -2094,7 +2095,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain) | |||
| 2094 | iommu_disable_dev_iotlb(info); | 2095 | iommu_disable_dev_iotlb(info); |
| 2095 | iommu_detach_dev(info->iommu, info->bus, info->devfn); | 2096 | iommu_detach_dev(info->iommu, info->bus, info->devfn); |
| 2096 | 2097 | ||
| 2097 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) { | 2098 | if (domain_type_is_vm(domain)) { |
| 2098 | iommu_detach_dependent_devices(info->iommu, info->dev); | 2099 | iommu_detach_dependent_devices(info->iommu, info->dev); |
| 2099 | /* clear this iommu in iommu_bmp, update iommu count | 2100 | /* clear this iommu in iommu_bmp, update iommu count |
| 2100 | * and capabilities | 2101 | * and capabilities |
| @@ -2160,8 +2161,6 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu, | |||
| 2160 | info->dev = dev; | 2161 | info->dev = dev; |
| 2161 | info->domain = domain; | 2162 | info->domain = domain; |
| 2162 | info->iommu = iommu; | 2163 | info->iommu = iommu; |
| 2163 | if (!dev) | ||
| 2164 | domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES; | ||
| 2165 | 2164 | ||
| 2166 | spin_lock_irqsave(&device_domain_lock, flags); | 2165 | spin_lock_irqsave(&device_domain_lock, flags); |
| 2167 | if (dev) | 2166 | if (dev) |
| @@ -2233,7 +2232,7 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw) | |||
| 2233 | } | 2232 | } |
| 2234 | 2233 | ||
| 2235 | /* Allocate and initialize new domain for the device */ | 2234 | /* Allocate and initialize new domain for the device */ |
| 2236 | domain = alloc_domain(false); | 2235 | domain = alloc_domain(0); |
| 2237 | if (!domain) | 2236 | if (!domain) |
| 2238 | return NULL; | 2237 | return NULL; |
| 2239 | 2238 | ||
| @@ -2408,12 +2407,10 @@ static int __init si_domain_init(int hw) | |||
| 2408 | struct intel_iommu *iommu; | 2407 | struct intel_iommu *iommu; |
| 2409 | int nid, ret = 0; | 2408 | int nid, ret = 0; |
| 2410 | 2409 | ||
| 2411 | si_domain = alloc_domain(false); | 2410 | si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY); |
| 2412 | if (!si_domain) | 2411 | if (!si_domain) |
| 2413 | return -EFAULT; | 2412 | return -EFAULT; |
| 2414 | 2413 | ||
| 2415 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | ||
| 2416 | |||
| 2417 | for_each_active_iommu(iommu, drhd) { | 2414 | for_each_active_iommu(iommu, drhd) { |
| 2418 | ret = iommu_attach_domain(si_domain, iommu); | 2415 | ret = iommu_attach_domain(si_domain, iommu); |
| 2419 | if (ret) { | 2416 | if (ret) { |
| @@ -3860,9 +3857,7 @@ static int device_notifier(struct notifier_block *nb, | |||
| 3860 | 3857 | ||
| 3861 | down_read(&dmar_global_lock); | 3858 | down_read(&dmar_global_lock); |
| 3862 | domain_remove_one_dev_info(domain, dev); | 3859 | domain_remove_one_dev_info(domain, dev); |
| 3863 | if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && | 3860 | if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices)) |
| 3864 | !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) && | ||
| 3865 | list_empty(&domain->devices)) | ||
| 3866 | domain_exit(domain); | 3861 | domain_exit(domain); |
| 3867 | up_read(&dmar_global_lock); | 3862 | up_read(&dmar_global_lock); |
| 3868 | 3863 | ||
| @@ -4167,8 +4162,7 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, | |||
| 4167 | domain_update_iommu_cap(domain); | 4162 | domain_update_iommu_cap(domain); |
| 4168 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); | 4163 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); |
| 4169 | 4164 | ||
| 4170 | if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && | 4165 | if (!domain_type_is_vm_or_si(domain)) { |
| 4171 | !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) { | ||
| 4172 | spin_lock_irqsave(&iommu->lock, tmp_flags); | 4166 | spin_lock_irqsave(&iommu->lock, tmp_flags); |
| 4173 | clear_bit(domain->id, iommu->domain_ids); | 4167 | clear_bit(domain->id, iommu->domain_ids); |
