| @@ -163,38 +163,6 @@ static phys_addr_t root_entry_uctp(struct root_entry *re) · 162 unmodified lines |
| 163 | 163 | return re->hi & VTD_PAGE_MASK; |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | | −static inline void context_clear_pasid_enable(struct context_entry *context) |
| 167 | | −{ |
| 168 | | − context->lo &= ~(1ULL << 11); |
| 169 | | −} |
| 170 | | − |
| 171 | | −static inline bool context_pasid_enabled(struct context_entry *context) |
| 172 | | −{ |
| 173 | | − return !!(context->lo & (1ULL << 11)); |
| 174 | | −} |
| 175 | | − |
| 176 | | −static inline void context_set_copied(struct context_entry *context) |
| 177 | | −{ |
| 178 | | − context->hi |= (1ull << 3); |
| 179 | | −} |
| 180 | | − |
| 181 | | −static inline bool context_copied(struct context_entry *context) |
| 182 | | −{ |
| 183 | | − return !!(context->hi & (1ULL << 3)); |
| 184 | | −} |
| 185 | | − |
| 186 | | −static inline bool __context_present(struct context_entry *context) |
| 187 | | −{ |
| 188 | | − return (context->lo & 1); |
| 189 | | −} |
| 190 | | − |
| 191 | | −bool context_present(struct context_entry *context) |
| 192 | | −{ |
| 193 | | − return context_pasid_enabled(context) ? |
| 194 | | − __context_present(context) : |
| 195 | | − __context_present(context) && !context_copied(context); |
| 196 | | −} |
| 197 | | − |
| 198 | 166 | static inline void context_set_present(struct context_entry *context) |
| 199 | 167 | { |
| 200 | 168 | context->lo |= 1; |
| @@ -242,6 +210,26 @@ static inline void context_clear_entry(struct context_entry *context) · 41 unmodified lines |
| 242 | 210 | context->hi = 0; |
| 243 | 211 | } |
| 244 | 212 | |
| 213 | +static inline bool context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn) |
| 214 | +{ |
| 215 | + if (!iommu->copied_tables) |
| 216 | + return false; |
| 217 | + |
| 218 | + return test_bit(((long)bus << 8) | devfn, iommu->copied_tables); |
| 219 | +} |
| 220 | + |
| 221 | +static inline void |
| 222 | +set_context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn) |
| 223 | +{ |
| 224 | + set_bit(((long)bus << 8) | devfn, iommu->copied_tables); |
| 225 | +} |
| 226 | + |
| 227 | +static inline void |
| 228 | +clear_context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn) |
| 229 | +{ |
| 230 | + clear_bit(((long)bus << 8) | devfn, iommu->copied_tables); |
| 231 | +} |
| 232 | + |
| 245 | 233 | /* |
| 246 | 234 | * This domain is a statically identity mapping domain. |
| 247 | 235 | * 1. This domain creats a static 1:1 mapping to all usable memory. |
| @@ -402,14 +390,36 @@ static inline int domain_pfn_supported(struct dmar_domain *domain, · 154 unmodified lines |
| 402 | 390 | return !(addr_width < BITS_PER_LONG && pfn >> addr_width); |
| 403 | 391 | } |
| 404 | 392 | |
| 393 | +/* |
| 394 | + * Calculate the Supported Adjusted Guest Address Widths of an IOMMU. |
| 395 | + * Refer to 11.4.2 of the VT-d spec for the encoding of each bit of |
| 396 | + * the returned SAGAW. |
| 397 | + */ |
| 398 | +static unsigned long __iommu_calculate_sagaw(struct intel_iommu *iommu) |
| 399 | +{ |
| 400 | + unsigned long fl_sagaw, sl_sagaw; |
| 401 | + |
| 402 | + fl_sagaw = BIT(2) | (cap_fl1gp_support(iommu->cap) ? BIT(3) : 0); |
| 403 | + sl_sagaw = cap_sagaw(iommu->cap); |
| 404 | + |
| 405 | + /* Second level only. */ |
| 406 | + if (!sm_supported(iommu) || !ecap_flts(iommu->ecap)) |
| 407 | + return sl_sagaw; |
| 408 | + |
| 409 | + /* First level only. */ |
| 410 | + if (!ecap_slts(iommu->ecap)) |
| 411 | + return fl_sagaw; |
| 412 | + |
| 413 | + return fl_sagaw & sl_sagaw; |
| 414 | +} |
| 415 | + |
| 405 | 416 | static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) |
| 406 | 417 | { |
| 407 | 418 | unsigned long sagaw; |
| 408 | 419 | int agaw; |
| 409 | 420 | |
| 410 | | − sagaw = cap_sagaw(iommu->cap); |
| 411 | | − for (agaw = width_to_agaw(max_gaw); |
| 412 | | − agaw >= 0; agaw--) { |
| 421 | + sagaw = __iommu_calculate_sagaw(iommu); |
| 422 | + for (agaw = width_to_agaw(max_gaw); agaw >= 0; agaw--) { |
| 413 | 423 | if (test_bit(agaw, &sagaw)) |
| 414 | 424 | break; |
| 415 | 425 | } |
| @@ -505,8 +515,9 @@ static int domain_update_device_node(struct dmar_domain *domain) · 89 unmodified lines |
| 505 | 515 | { |
| 506 | 516 | struct device_domain_info *info; |
| 507 | 517 | int nid = NUMA_NO_NODE; |
| 518 | + unsigned long flags; |
| 508 | 519 | |
| 509 | | − spin_lock(&domain->lock); |
| 520 | + spin_lock_irqsave(&domain->lock, flags); |
| 510 | 521 | list_for_each_entry(info, &domain->devices, link) { |
| 511 | 522 | /* |
| 512 | 523 | * There could possibly be multiple device numa nodes as devices |
| @@ -518,7 +529,7 @@ static int domain_update_device_node(struct dmar_domain *domain) · 5 unmodified lines |
| 518 | 529 | if (nid != NUMA_NO_NODE) |
| 519 | 530 | break; |
| 520 | 531 | } |
| 521 | | − spin_unlock(&domain->lock); |
| 532 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 522 | 533 | |
| 523 | 534 | return nid; |
| 524 | 535 | } |
| @@ -578,6 +589,13 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus, · 53 unmodified lines |
| 578 | 589 | struct context_entry *context; |
| 579 | 590 | u64 *entry; |
| 580 | 591 | |
| 592 | + /* |
| 593 | + * Except that the caller requested to allocate a new entry, |
| 594 | + * returning a copied context entry makes no sense. |
| 595 | + */ |
| 596 | + if (!alloc && context_copied(iommu, bus, devfn)) |
| 597 | + return NULL; |
| 598 | + |
| 581 | 599 | entry = &root->lo; |
| 582 | 600 | if (sm_supported(iommu)) { |
| 583 | 601 | if (devfn >= 0x80) { |
| @@ -795,32 +813,11 @@ static void free_context_table(struct intel_iommu *iommu) · 211 unmodified lines |
| 795 | 813 | } |
| 796 | 814 | |
| 797 | 815 | #ifdef CONFIG_DMAR_DEBUG |
| 798 | | −static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn, u8 bus, u8 devfn) |
| 816 | +static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn, |
| 817 | + u8 bus, u8 devfn, struct dma_pte *parent, int level) |
| 799 | 818 | { |
| 800 | | − struct device_domain_info *info; |
| 801 | | − struct dma_pte *parent, *pte; |
| 802 | | − struct dmar_domain *domain; |
| 803 | | − struct pci_dev *pdev; |
| 804 | | − int offset, level; |
| 805 | | − |
| 806 | | − pdev = pci_get_domain_bus_and_slot(iommu->segment, bus, devfn); |
| 807 | | − if (!pdev) |
| 808 | | − return; |
| 809 | | − |
| 810 | | − info = dev_iommu_priv_get(&pdev->dev); |
| 811 | | − if (!info || !info->domain) { |
| 812 | | − pr_info("device [%02x:%02x.%d] not probed\n", |
| 813 | | − bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
| 814 | | − return; |
| 815 | | − } |
| 816 | | − |
| 817 | | − domain = info->domain; |
| 818 | | − level = agaw_to_level(domain->agaw); |
| 819 | | − parent = domain->pgd; |
| 820 | | − if (!parent) { |
| 821 | | − pr_info("no page table setup\n"); |
| 822 | | − return; |
| 823 | | − } |
| 819 | + struct dma_pte *pte; |
| 820 | + int offset; |
| 824 | 821 | |
| 825 | 822 | while (1) { |
| 826 | 823 | offset = pfn_level_offset(pfn, level); |
| @@ -847,9 +844,10 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, · 20 unmodified lines |
| 847 | 844 | struct pasid_entry *entries, *pte; |
| 848 | 845 | struct context_entry *ctx_entry; |
| 849 | 846 | struct root_entry *rt_entry; |
| 847 | + int i, dir_index, index, level; |
| 850 | 848 | u8 devfn = source_id & 0xff; |
| 851 | 849 | u8 bus = source_id >> 8; |
| 852 | | − int i, dir_index, index; |
| 850 | + struct dma_pte *pgtable; |
| 853 | 851 | |
| 854 | 852 | pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr); |
| 855 | 853 | |
| @@ -877,8 +875,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, · 21 unmodified lines |
| 877 | 875 | ctx_entry->hi, ctx_entry->lo); |
| 878 | 876 | |
| 879 | 877 | /* legacy mode does not require PASID entries */ |
| 880 | | − if (!sm_supported(iommu)) |
| 878 | + if (!sm_supported(iommu)) { |
| 879 | + level = agaw_to_level(ctx_entry->hi & 7); |
| 880 | + pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK); |
| 881 | 881 | goto pgtable_walk; |
| 882 | + } |
| 882 | 883 | |
| 883 | 884 | /* get the pointer to pasid directory entry */ |
| 884 | 885 | dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK); |
| @@ -905,8 +906,16 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, · 20 unmodified lines |
| 905 | 906 | for (i = 0; i < ARRAY_SIZE(pte->val); i++) |
| 906 | 907 | pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]); |
| 907 | 908 | |
| 909 | + if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) { |
| 910 | + level = pte->val[2] & BIT_ULL(2) ? 5 : 4; |
| 911 | + pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK); |
| 912 | + } else { |
| 913 | + level = agaw_to_level((pte->val[0] >> 2) & 0x7); |
| 914 | + pgtable = phys_to_virt(pte->val[0] & VTD_PAGE_MASK); |
| 915 | + } |
| 916 | + |
| 908 | 917 | pgtable_walk: |
| 909 | | − pgtable_walk(iommu, addr >> VTD_PAGE_SHIFT, bus, devfn); |
| 918 | + pgtable_walk(iommu, addr >> VTD_PAGE_SHIFT, bus, devfn, pgtable, level); |
| 910 | 919 | } |
| 911 | 920 | #endif |
| 912 | 921 | |
| @@ -1345,19 +1354,20 @@ iommu_support_dev_iotlb(struct dmar_domain *domain, struct intel_iommu *iommu, · 432 unmodified lines |
| 1345 | 1354 | u8 bus, u8 devfn) |
| 1346 | 1355 | { |
| 1347 | 1356 | struct device_domain_info *info; |
| 1357 | + unsigned long flags; |
| 1348 | 1358 | |
| 1349 | 1359 | if (!iommu->qi) |
| 1350 | 1360 | return NULL; |
| 1351 | 1361 | |
| 1352 | | − spin_lock(&domain->lock); |
| 1362 | + spin_lock_irqsave(&domain->lock, flags); |
| 1353 | 1363 | list_for_each_entry(info, &domain->devices, link) { |
| 1354 | 1364 | if (info->iommu == iommu && info->bus == bus && |
| 1355 | 1365 | info->devfn == devfn) { |
| 1356 | | − spin_unlock(&domain->lock); |
| 1366 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 1357 | 1367 | return info->ats_supported ? info : NULL; |
| 1358 | 1368 | } |
| 1359 | 1369 | } |
| 1360 | | − spin_unlock(&domain->lock); |
| 1370 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 1361 | 1371 | |
| 1362 | 1372 | return NULL; |
| 1363 | 1373 | } |
| @@ -1366,8 +1376,9 @@ static void domain_update_iotlb(struct dmar_domain *domain) · 2 unmodified lines |
| 1366 | 1376 | { |
| 1367 | 1377 | struct device_domain_info *info; |
| 1368 | 1378 | bool has_iotlb_device = false; |
| 1379 | + unsigned long flags; |
| 1369 | 1380 | |
| 1370 | | − spin_lock(&domain->lock); |
| 1381 | + spin_lock_irqsave(&domain->lock, flags); |
| 1371 | 1382 | list_for_each_entry(info, &domain->devices, link) { |
| 1372 | 1383 | if (info->ats_enabled) { |
| 1373 | 1384 | has_iotlb_device = true; |
| @@ -1375,7 +1386,7 @@ static void domain_update_iotlb(struct dmar_domain *domain) · 1 unmodified line |
| 1375 | 1386 | } |
| 1376 | 1387 | } |
| 1377 | 1388 | domain->has_iotlb_device = has_iotlb_device; |
| 1378 | | − spin_unlock(&domain->lock); |
| 1389 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 1379 | 1390 | } |
| 1380 | 1391 | |
| 1381 | 1392 | static void iommu_enable_dev_iotlb(struct device_domain_info *info) |
| @@ -1467,14 +1478,15 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, · 85 unmodified lines |
| 1467 | 1478 | u64 addr, unsigned mask) |
| 1468 | 1479 | { |
| 1469 | 1480 | struct device_domain_info *info; |
| 1481 | + unsigned long flags; |
| 1470 | 1482 | |
| 1471 | 1483 | if (!domain->has_iotlb_device) |
| 1472 | 1484 | return; |
| 1473 | 1485 | |
| 1474 | | − spin_lock(&domain->lock); |
| 1486 | + spin_lock_irqsave(&domain->lock, flags); |
| 1475 | 1487 | list_for_each_entry(info, &domain->devices, link) |
| 1476 | 1488 | __iommu_flush_dev_iotlb(info, addr, mask); |
| 1477 | | − spin_unlock(&domain->lock); |
| 1489 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 1478 | 1490 | } |
| 1479 | 1491 | |
| 1480 | 1492 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, |
| @@ -1688,6 +1700,11 @@ static void free_dmar_iommu(struct intel_iommu *iommu) · 207 unmodified lines |
| 1688 | 1700 | iommu->domain_ids = NULL; |
| 1689 | 1701 | } |
| 1690 | 1702 | |
| 1703 | + if (iommu->copied_tables) { |
| 1704 | + bitmap_free(iommu->copied_tables); |
| 1705 | + iommu->copied_tables = NULL; |
| 1706 | + } |
| 1707 | + |
| 1691 | 1708 | /* free context mapping */ |
| 1692 | 1709 | free_context_table(iommu); |
| 1693 | 1710 | |
| @@ -1913,7 +1930,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, · 219 unmodified lines |
| 1913 | 1930 | goto out_unlock; |
| 1914 | 1931 | |
| 1915 | 1932 | ret = 0; |
| 1916 | | − if (context_present(context)) |
| 1933 | + if (context_present(context) && !context_copied(iommu, bus, devfn)) |
| 1917 | 1934 | goto out_unlock; |
| 1918 | 1935 | |
| 1919 | 1936 | /* |
| @@ -1925,7 +1942,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, · 5 unmodified lines |
| 1925 | 1942 | * in-flight DMA will exist, and we don't need to worry anymore |
| 1926 | 1943 | * hereafter. |
| 1927 | 1944 | */ |
| 1928 | | − if (context_copied(context)) { |
| 1945 | + if (context_copied(iommu, bus, devfn)) { |
| 1929 | 1946 | u16 did_old = context_domain_id(context); |
| 1930 | 1947 | |
| 1931 | 1948 | if (did_old < cap_ndoms(iommu->cap)) { |
| @@ -1936,6 +1953,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain, · 4 unmodified lines |
| 1936 | 1953 | iommu->flush.flush_iotlb(iommu, did_old, 0, 0, |
| 1937 | 1954 | DMA_TLB_DSI_FLUSH); |
| 1938 | 1955 | } |
| 1956 | + |
| 1957 | + clear_context_copied(iommu, bus, devfn); |
| 1939 | 1958 | } |
| 1940 | 1959 | |
| 1941 | 1960 | context_clear_entry(context); |
| @@ -2429,6 +2448,7 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev) · 487 unmodified lines |
| 2429 | 2448 | { |
| 2430 | 2449 | struct device_domain_info *info = dev_iommu_priv_get(dev); |
| 2431 | 2450 | struct intel_iommu *iommu; |
| 2451 | + unsigned long flags; |
| 2432 | 2452 | u8 bus, devfn; |
| 2433 | 2453 | int ret; |
| 2434 | 2454 | |
| @@ -2440,9 +2460,9 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev) · 5 unmodified lines |
| 2440 | 2460 | if (ret) |
| 2441 | 2461 | return ret; |
| 2442 | 2462 | info->domain = domain; |
| 2443 | | − spin_lock(&domain->lock); |
| 2463 | + spin_lock_irqsave(&domain->lock, flags); |
| 2444 | 2464 | list_add(&info->link, &domain->devices); |
| 2445 | | − spin_unlock(&domain->lock); |
| 2465 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 2446 | 2466 | |
| 2447 | 2467 | /* PASID table is mandatory for a PCI device in scalable mode. */ |
| 2448 | 2468 | if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { |
| @@ -2684,32 +2704,14 @@ static int copy_context_table(struct intel_iommu *iommu, · 235 unmodified lines |
| 2684 | 2704 | /* Now copy the context entry */ |
| 2685 | 2705 | memcpy(&ce, old_ce + idx, sizeof(ce)); |
| 2686 | 2706 | |
| 2687 | | − if (!__context_present(&ce)) |
| 2707 | + if (!context_present(&ce)) |
| 2688 | 2708 | continue; |
| 2689 | 2709 | |
| 2690 | 2710 | did = context_domain_id(&ce); |
| 2691 | 2711 | if (did >= 0 && did < cap_ndoms(iommu->cap)) |
| 2692 | 2712 | set_bit(did, iommu->domain_ids); |
| 2693 | 2713 | |
| 2694 | | − /* |
| 2695 | | − * We need a marker for copied context entries. This |
| 2696 | | − * marker needs to work for the old format as well as |
| 2697 | | − * for extended context entries. |
| 2698 | | − * |
| 2699 | | − * Bit 67 of the context entry is used. In the old |
| 2700 | | − * format this bit is available to software, in the |
| 2701 | | − * extended format it is the PGE bit, but PGE is ignored |
| 2702 | | − * by HW if PASIDs are disabled (and thus still |
| 2703 | | − * available). |
| 2704 | | − * |
| 2705 | | − * So disable PASIDs first and then mark the entry |
| 2706 | | − * copied. This means that we don't copy PASID |
| 2707 | | − * translations from the old kernel, but this is fine as |
| 2708 | | − * faults there are not fatal. |
| 2709 | | − */ |
| 2710 | | − context_clear_pasid_enable(&ce); |
| 2711 | | − context_set_copied(&ce); |
| 2712 | | − |
| 2714 | + set_context_copied(iommu, bus, devfn); |
| 2713 | 2715 | new_ce[idx] = ce; |
| 2714 | 2716 | } |
| 2715 | 2717 | |
| @@ -2735,8 +2737,8 @@ static int copy_translation_tables(struct intel_iommu *iommu) · 19 unmodified lines |
| 2735 | 2737 | bool new_ext, ext; |
| 2736 | 2738 | |
| 2737 | 2739 | rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG); |
| 2738 | | − ext = !!(rtaddr_reg & DMA_RTADDR_RTT); |
| 2739 | | − new_ext = !!ecap_ecs(iommu->ecap); |
| 2740 | + ext = !!(rtaddr_reg & DMA_RTADDR_SMT); |
| 2741 | + new_ext = !!sm_supported(iommu); |
| 2740 | 2742 | |
| 2741 | 2743 | /* |
| 2742 | 2744 | * The RTT bit can only be changed when translation is disabled, |
| @@ -2747,6 +2749,10 @@ static int copy_translation_tables(struct intel_iommu *iommu) · 4 unmodified lines |
| 2747 | 2749 | if (new_ext != ext) |
| 2748 | 2750 | return -EINVAL; |
| 2749 | 2751 | |
| 2752 | + iommu->copied_tables = bitmap_zalloc(BIT_ULL(16), GFP_KERNEL); |
| 2753 | + if (!iommu->copied_tables) |
| 2754 | + return -ENOMEM; |
| 2755 | + |
| 2750 | 2756 | old_rt_phys = rtaddr_reg & VTD_PAGE_MASK; |
| 2751 | 2757 | if (!old_rt_phys) |
| 2752 | 2758 | return -EINVAL; |
| @@ -3013,13 +3019,7 @@ static int __init init_dmars(void) · 260 unmodified lines |
| 3013 | 3019 | |
| 3014 | 3020 | #ifdef CONFIG_INTEL_IOMMU_SVM |
| 3015 | 3021 | if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) { |
| 3016 | | − /* |
| 3017 | | − * Call dmar_alloc_hwirq() with dmar_global_lock held, |
| 3018 | | − * could cause possible lock race condition. |
| 3019 | | − */ |
| 3020 | | − up_write(&dmar_global_lock); |
| 3021 | 3022 | ret = intel_svm_enable_prq(iommu); |
| 3022 | | − down_write(&dmar_global_lock); |
| 3023 | 3023 | if (ret) |
| 3024 | 3024 | goto free_iommu; |
| 3025 | 3025 | } |
| @@ -3932,7 +3932,6 @@ int __init intel_iommu_init(void) · 906 unmodified lines |
| 3932 | 3932 | force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) || |
| 3933 | 3933 | platform_optin_force_iommu(); |
| 3934 | 3934 | |
| 3935 | | − down_write(&dmar_global_lock); |
| 3936 | 3935 | if (dmar_table_init()) { |
| 3937 | 3936 | if (force_on) |
| 3938 | 3937 | panic("tboot: Failed to initialize DMAR table\n"); |
| @@ -3945,16 +3944,6 @@ int __init intel_iommu_init(void) · 6 unmodified lines |
| 3945 | 3944 | goto out_free_dmar; |
| 3946 | 3945 | } |
| 3947 | 3946 | |
| 3948 | | − up_write(&dmar_global_lock); |
| 3949 | | − |
| 3950 | | − /* |
| 3951 | | − * The bus notifier takes the dmar_global_lock, so lockdep will |
| 3952 | | − * complain later when we register it under the lock. |
| 3953 | | − */ |
| 3954 | | − dmar_register_bus_notifier(); |
| 3955 | | − |
| 3956 | | − down_write(&dmar_global_lock); |
| 3957 | | − |
| 3958 | 3947 | if (!no_iommu) |
| 3959 | 3948 | intel_iommu_debugfs_init(); |
| 3960 | 3949 | |
| @@ -3999,11 +3988,9 @@ int __init intel_iommu_init(void) · 38 unmodified lines |
| 3999 | 3988 | pr_err("Initialization failed\n"); |
| 4000 | 3989 | goto out_free_dmar; |
| 4001 | 3990 | } |
| 4002 | | − up_write(&dmar_global_lock); |
| 4003 | 3991 | |
| 4004 | 3992 | init_iommu_pm_ops(); |
| 4005 | 3993 | |
| 4006 | | − down_read(&dmar_global_lock); |
| 4007 | 3994 | for_each_active_iommu(iommu, drhd) { |
| 4008 | 3995 | /* |
| 4009 | 3996 | * The flush queue implementation does not perform |
| @@ -4021,13 +4008,11 @@ int __init intel_iommu_init(void) · 11 unmodified lines |
| 4021 | 4008 | "%s", iommu->name); |
| 4022 | 4009 | iommu_device_register(&iommu->iommu, &intel_iommu_ops, NULL); |
| 4023 | 4010 | } |
| 4024 | | − up_read(&dmar_global_lock); |
| 4025 | 4011 | |
| 4026 | 4012 | bus_set_iommu(&pci_bus_type, &intel_iommu_ops); |
| 4027 | 4013 | if (si_domain && !hw_pass_through) |
| 4028 | 4014 | register_memory_notifier(&intel_iommu_memory_nb); |
| 4029 | 4015 | |
| 4030 | | − down_read(&dmar_global_lock); |
| 4031 | 4016 | if (probe_acpi_namespace_devices()) |
| 4032 | 4017 | pr_warn("ACPI name space devices didn't probe correctly\n"); |
| 4033 | 4018 | |
| @@ -4038,17 +4023,15 @@ int __init intel_iommu_init(void) · 4 unmodified lines |
| 4038 | 4023 | |
| 4039 | 4024 | iommu_disable_protect_mem_regions(iommu); |
| 4040 | 4025 | } |
| 4041 | | − up_read(&dmar_global_lock); |
| 4042 | | − |
| 4043 | | − pr_info("Intel(R) Virtualization Technology for Directed I/O\n"); |
| 4044 | 4026 | |
| 4045 | 4027 | intel_iommu_enabled = 1; |
| 4028 | + dmar_register_bus_notifier(); |
| 4029 | + pr_info("Intel(R) Virtualization Technology for Directed I/O\n"); |
| 4046 | 4030 | |
| 4047 | 4031 | return 0; |
| 4048 | 4032 | |
| 4049 | 4033 | out_free_dmar: |
| 4050 | 4034 | intel_iommu_free_dmars(); |
| 4051 | | − up_write(&dmar_global_lock); |
| 4052 | 4035 | return ret; |
| 4053 | 4036 | } |
| 4054 | 4037 | |
| @@ -4080,6 +4063,7 @@ static void dmar_remove_one_dev_info(struct device *dev) · 25 unmodified lines |
| 4080 | 4063 | struct device_domain_info *info = dev_iommu_priv_get(dev); |
| 4081 | 4064 | struct dmar_domain *domain = info->domain; |
| 4082 | 4065 | struct intel_iommu *iommu = info->iommu; |
| 4066 | + unsigned long flags; |
| 4083 | 4067 | |
| 4084 | 4068 | if (!dev_is_real_dma_subdevice(info->dev)) { |
| 4085 | 4069 | if (dev_is_pci(info->dev) && sm_supported(iommu)) |
| @@ -4091,9 +4075,9 @@ static void dmar_remove_one_dev_info(struct device *dev) · 5 unmodified lines |
| 4091 | 4075 | intel_pasid_free_table(info->dev); |
| 4092 | 4076 | } |
| 4093 | 4077 | |
| 4094 | | − spin_lock(&domain->lock); |
| 4078 | + spin_lock_irqsave(&domain->lock, flags); |
| 4095 | 4079 | list_del(&info->link); |
| 4096 | | − spin_unlock(&domain->lock); |
| 4080 | + spin_unlock_irqrestore(&domain->lock, flags); |
| 4097 | 4081 | |
| 4098 | 4082 | domain_detach_iommu(domain, iommu); |
| 4099 | 4083 | info->domain = NULL; |
| @@ -4412,19 +4396,20 @@ static void domain_set_force_snooping(struct dmar_domain *domain) · 312 unmodified lines |
| 4412 | 4396 | static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domain) |
| 4413 | 4397 | { |
| 4414 | 4398 | struct dmar_domain *dmar_domain = to_dmar_domain(domain); |
| 4399 | + unsigned long flags; |
| 4415 | 4400 | |
| 4416 | 4401 | if (dmar_domain->force_snooping) |
| 4417 | 4402 | return true; |
| 4418 | 4403 | |
| 4419 | | − spin_lock(&dmar_domain->lock); |
| 4404 | + spin_lock_irqsave(&dmar_domain->lock, flags); |
| 4420 | 4405 | if (!domain_support_force_snooping(dmar_domain)) { |
| 4421 | | − spin_unlock(&dmar_domain->lock); |
| 4406 | + spin_unlock_irqrestore(&dmar_domain->lock, flags); |
| 4422 | 4407 | return false; |
| 4423 | 4408 | } |
| 4424 | 4409 | |
| 4425 | 4410 | domain_set_force_snooping(dmar_domain); |
| 4426 | 4411 | dmar_domain->force_snooping = true; |
| 4427 | | − spin_unlock(&dmar_domain->lock); |
| 4412 | + spin_unlock_irqrestore(&dmar_domain->lock, flags); |
| 4428 | 4413 | |
| 4429 | 4414 | return true; |
| 4430 | 4415 | } |