diff options
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/intel-iommu.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c9c6053198d4..132f93b05154 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -48,8 +48,6 @@ | |||
48 | #define ROOT_SIZE VTD_PAGE_SIZE | 48 | #define ROOT_SIZE VTD_PAGE_SIZE |
49 | #define CONTEXT_SIZE VTD_PAGE_SIZE | 49 | #define CONTEXT_SIZE VTD_PAGE_SIZE |
50 | 50 | ||
51 | #define IS_BRIDGE_HOST_DEVICE(pdev) \ | ||
52 | ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST) | ||
53 | #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) | 51 | #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) |
54 | #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) | 52 | #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) |
55 | #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) | 53 | #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) |
@@ -356,10 +354,18 @@ static int hw_pass_through = 1; | |||
356 | /* si_domain contains mulitple devices */ | 354 | /* si_domain contains mulitple devices */ |
357 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2) | 355 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2) |
358 | 356 | ||
357 | /* define the limit of IOMMUs supported in each domain */ | ||
358 | #ifdef CONFIG_X86 | ||
359 | # define IOMMU_UNITS_SUPPORTED MAX_IO_APICS | ||
360 | #else | ||
361 | # define IOMMU_UNITS_SUPPORTED 64 | ||
362 | #endif | ||
363 | |||
359 | struct dmar_domain { | 364 | struct dmar_domain { |
360 | int id; /* domain id */ | 365 | int id; /* domain id */ |
361 | int nid; /* node id */ | 366 | int nid; /* node id */ |
362 | unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/ | 367 | DECLARE_BITMAP(iommu_bmp, IOMMU_UNITS_SUPPORTED); |
368 | /* bitmap of iommus this domain uses*/ | ||
363 | 369 | ||
364 | struct list_head devices; /* all devices' list */ | 370 | struct list_head devices; /* all devices' list */ |
365 | struct iova_domain iovad; /* iova's that belong to this domain */ | 371 | struct iova_domain iovad; /* iova's that belong to this domain */ |
@@ -571,7 +577,7 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) | |||
571 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); | 577 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); |
572 | BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY); | 578 | BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY); |
573 | 579 | ||
574 | iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | 580 | iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus); |
575 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) | 581 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) |
576 | return NULL; | 582 | return NULL; |
577 | 583 | ||
@@ -584,7 +590,7 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) | |||
584 | 590 | ||
585 | domain->iommu_coherency = 1; | 591 | domain->iommu_coherency = 1; |
586 | 592 | ||
587 | for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { | 593 | for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { |
588 | if (!ecap_coherent(g_iommus[i]->ecap)) { | 594 | if (!ecap_coherent(g_iommus[i]->ecap)) { |
589 | domain->iommu_coherency = 0; | 595 | domain->iommu_coherency = 0; |
590 | break; | 596 | break; |
@@ -598,7 +604,7 @@ static void domain_update_iommu_snooping(struct dmar_domain *domain) | |||
598 | 604 | ||
599 | domain->iommu_snooping = 1; | 605 | domain->iommu_snooping = 1; |
600 | 606 | ||
601 | for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { | 607 | for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { |
602 | if (!ecap_sc_support(g_iommus[i]->ecap)) { | 608 | if (!ecap_sc_support(g_iommus[i]->ecap)) { |
603 | domain->iommu_snooping = 0; | 609 | domain->iommu_snooping = 0; |
604 | break; | 610 | break; |
@@ -1241,7 +1247,7 @@ static int iommu_init_domains(struct intel_iommu *iommu) | |||
1241 | unsigned long nlongs; | 1247 | unsigned long nlongs; |
1242 | 1248 | ||
1243 | ndomains = cap_ndoms(iommu->cap); | 1249 | ndomains = cap_ndoms(iommu->cap); |
1244 | pr_debug("IOMMU %d: Number of Domains supportd <%ld>\n", iommu->seq_id, | 1250 | pr_debug("IOMMU %d: Number of Domains supported <%ld>\n", iommu->seq_id, |
1245 | ndomains); | 1251 | ndomains); |
1246 | nlongs = BITS_TO_LONGS(ndomains); | 1252 | nlongs = BITS_TO_LONGS(ndomains); |
1247 | 1253 | ||
@@ -1334,7 +1340,7 @@ static struct dmar_domain *alloc_domain(void) | |||
1334 | return NULL; | 1340 | return NULL; |
1335 | 1341 | ||
1336 | domain->nid = -1; | 1342 | domain->nid = -1; |
1337 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 1343 | memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp)); |
1338 | domain->flags = 0; | 1344 | domain->flags = 0; |
1339 | 1345 | ||
1340 | return domain; | 1346 | return domain; |
@@ -1360,7 +1366,7 @@ static int iommu_attach_domain(struct dmar_domain *domain, | |||
1360 | 1366 | ||
1361 | domain->id = num; | 1367 | domain->id = num; |
1362 | set_bit(num, iommu->domain_ids); | 1368 | set_bit(num, iommu->domain_ids); |
1363 | set_bit(iommu->seq_id, &domain->iommu_bmp); | 1369 | set_bit(iommu->seq_id, domain->iommu_bmp); |
1364 | iommu->domains[num] = domain; | 1370 | iommu->domains[num] = domain; |
1365 | spin_unlock_irqrestore(&iommu->lock, flags); | 1371 | spin_unlock_irqrestore(&iommu->lock, flags); |
1366 | 1372 | ||
@@ -1385,7 +1391,7 @@ static void iommu_detach_domain(struct dmar_domain *domain, | |||
1385 | 1391 | ||
1386 | if (found) { | 1392 | if (found) { |
1387 | clear_bit(num, iommu->domain_ids); | 1393 | clear_bit(num, iommu->domain_ids); |
1388 | clear_bit(iommu->seq_id, &domain->iommu_bmp); | 1394 | clear_bit(iommu->seq_id, domain->iommu_bmp); |
1389 | iommu->domains[num] = NULL; | 1395 | iommu->domains[num] = NULL; |
1390 | } | 1396 | } |
1391 | spin_unlock_irqrestore(&iommu->lock, flags); | 1397 | spin_unlock_irqrestore(&iommu->lock, flags); |
@@ -1527,7 +1533,7 @@ static void domain_exit(struct dmar_domain *domain) | |||
1527 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); | 1533 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
1528 | 1534 | ||
1529 | for_each_active_iommu(iommu, drhd) | 1535 | for_each_active_iommu(iommu, drhd) |
1530 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) | 1536 | if (test_bit(iommu->seq_id, domain->iommu_bmp)) |
1531 | iommu_detach_domain(domain, iommu); | 1537 | iommu_detach_domain(domain, iommu); |
1532 | 1538 | ||
1533 | free_domain_mem(domain); | 1539 | free_domain_mem(domain); |
@@ -1653,7 +1659,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
1653 | spin_unlock_irqrestore(&iommu->lock, flags); | 1659 | spin_unlock_irqrestore(&iommu->lock, flags); |
1654 | 1660 | ||
1655 | spin_lock_irqsave(&domain->iommu_lock, flags); | 1661 | spin_lock_irqsave(&domain->iommu_lock, flags); |
1656 | if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) { | 1662 | if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) { |
1657 | domain->iommu_count++; | 1663 | domain->iommu_count++; |
1658 | if (domain->iommu_count == 1) | 1664 | if (domain->iommu_count == 1) |
1659 | domain->nid = iommu->node; | 1665 | domain->nid = iommu->node; |
@@ -2369,18 +2375,18 @@ static int __init iommu_prepare_static_identity_mapping(int hw) | |||
2369 | return -EFAULT; | 2375 | return -EFAULT; |
2370 | 2376 | ||
2371 | for_each_pci_dev(pdev) { | 2377 | for_each_pci_dev(pdev) { |
2372 | /* Skip Host/PCI Bridge devices */ | ||
2373 | if (IS_BRIDGE_HOST_DEVICE(pdev)) | ||
2374 | continue; | ||
2375 | if (iommu_should_identity_map(pdev, 1)) { | 2378 | if (iommu_should_identity_map(pdev, 1)) { |
2376 | printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", | ||
2377 | hw ? "hardware" : "software", pci_name(pdev)); | ||
2378 | |||
2379 | ret = domain_add_dev_info(si_domain, pdev, | 2379 | ret = domain_add_dev_info(si_domain, pdev, |
2380 | hw ? CONTEXT_TT_PASS_THROUGH : | 2380 | hw ? CONTEXT_TT_PASS_THROUGH : |
2381 | CONTEXT_TT_MULTI_LEVEL); | 2381 | CONTEXT_TT_MULTI_LEVEL); |
2382 | if (ret) | 2382 | if (ret) { |
2383 | /* device not associated with an iommu */ | ||
2384 | if (ret == -ENODEV) | ||
2385 | continue; | ||
2383 | return ret; | 2386 | return ret; |
2387 | } | ||
2388 | pr_info("IOMMU: %s identity mapping for device %s\n", | ||
2389 | hw ? "hardware" : "software", pci_name(pdev)); | ||
2384 | } | 2390 | } |
2385 | } | 2391 | } |
2386 | 2392 | ||
@@ -2402,12 +2408,17 @@ static int __init init_dmars(void) | |||
2402 | * endfor | 2408 | * endfor |
2403 | */ | 2409 | */ |
2404 | for_each_drhd_unit(drhd) { | 2410 | for_each_drhd_unit(drhd) { |
2405 | g_num_of_iommus++; | ||
2406 | /* | 2411 | /* |
2407 | * lock not needed as this is only incremented in the single | 2412 | * lock not needed as this is only incremented in the single |
2408 | * threaded kernel __init code path all other access are read | 2413 | * threaded kernel __init code path all other access are read |
2409 | * only | 2414 | * only |
2410 | */ | 2415 | */ |
2416 | if (g_num_of_iommus < IOMMU_UNITS_SUPPORTED) { | ||
2417 | g_num_of_iommus++; | ||
2418 | continue; | ||
2419 | } | ||
2420 | printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n", | ||
2421 | IOMMU_UNITS_SUPPORTED); | ||
2411 | } | 2422 | } |
2412 | 2423 | ||
2413 | g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), | 2424 | g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), |
@@ -3748,7 +3759,7 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, | |||
3748 | if (found == 0) { | 3759 | if (found == 0) { |
3749 | unsigned long tmp_flags; | 3760 | unsigned long tmp_flags; |
3750 | spin_lock_irqsave(&domain->iommu_lock, tmp_flags); | 3761 | spin_lock_irqsave(&domain->iommu_lock, tmp_flags); |
3751 | clear_bit(iommu->seq_id, &domain->iommu_bmp); | 3762 | clear_bit(iommu->seq_id, domain->iommu_bmp); |
3752 | domain->iommu_count--; | 3763 | domain->iommu_count--; |
3753 | domain_update_iommu_cap(domain); | 3764 | domain_update_iommu_cap(domain); |
3754 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); | 3765 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); |
@@ -3790,7 +3801,7 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) | |||
3790 | */ | 3801 | */ |
3791 | spin_lock_irqsave(&domain->iommu_lock, flags2); | 3802 | spin_lock_irqsave(&domain->iommu_lock, flags2); |
3792 | if (test_and_clear_bit(iommu->seq_id, | 3803 | if (test_and_clear_bit(iommu->seq_id, |
3793 | &domain->iommu_bmp)) { | 3804 | domain->iommu_bmp)) { |
3794 | domain->iommu_count--; | 3805 | domain->iommu_count--; |
3795 | domain_update_iommu_cap(domain); | 3806 | domain_update_iommu_cap(domain); |
3796 | } | 3807 | } |
@@ -3815,7 +3826,7 @@ static struct dmar_domain *iommu_alloc_vm_domain(void) | |||
3815 | 3826 | ||
3816 | domain->id = vm_domid++; | 3827 | domain->id = vm_domid++; |
3817 | domain->nid = -1; | 3828 | domain->nid = -1; |
3818 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 3829 | memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp)); |
3819 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; | 3830 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; |
3820 | 3831 | ||
3821 | return domain; | 3832 | return domain; |