diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-02 19:51:09 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-02 19:51:09 -0400 |
| commit | 405d7ca51597645f3be850574d6c10f01be11e8d (patch) | |
| tree | 9461326f1f8e8c51f3d325702f6e0c6946fb0f67 | |
| parent | 7c5371c403abb29f01bc6cff6c5096abdf2dc524 (diff) | |
| parent | 6a43e574c5af7d9bd084992b1c9c3cdbc3b6c0e9 (diff) | |
Merge git://git.infradead.org/iommu-2.6
* git://git.infradead.org/iommu-2.6: (38 commits)
intel-iommu: Don't keep freeing page zero in dma_pte_free_pagetable()
intel-iommu: Introduce first_pte_in_page() to simplify PTE-setting loops
intel-iommu: Use cmpxchg64_local() for setting PTEs
intel-iommu: Warn about unmatched unmap requests
intel-iommu: Kill superfluous mapping_lock
intel-iommu: Ensure that PTE writes are 64-bit atomic, even on i386
intel-iommu: Make iommu=pt work on i386 too
intel-iommu: Performance improvement for dma_pte_free_pagetable()
intel-iommu: Don't free too much in dma_pte_free_pagetable()
intel-iommu: dump mappings but don't die on pte already set
intel-iommu: Combine domain_pfn_mapping() and domain_sg_mapping()
intel-iommu: Introduce domain_sg_mapping() to speed up intel_map_sg()
intel-iommu: Simplify __intel_alloc_iova()
intel-iommu: Performance improvement for domain_pfn_mapping()
intel-iommu: Performance improvement for dma_pte_clear_range()
intel-iommu: Clean up iommu_domain_identity_map()
intel-iommu: Remove last use of PHYSICAL_PAGE_MASK, for reserving PCI BARs
intel-iommu: Make iommu_flush_iotlb_psi() take pfn as argument
intel-iommu: Change aligned_size() to aligned_nrpages()
intel-iommu: Clean up intel_map_sg(), remove domain_page_mapping()
...
| -rw-r--r-- | arch/x86/Kconfig | 15 | ||||
| -rw-r--r-- | arch/x86/kernel/pci-dma.c | 2 | ||||
| -rw-r--r-- | drivers/pci/intel-iommu.c | 695 |
3 files changed, 353 insertions, 359 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d1430ef6b4f9..c07f72205909 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -1913,25 +1913,14 @@ config DMAR_DEFAULT_ON | |||
| 1913 | recommended you say N here while the DMAR code remains | 1913 | recommended you say N here while the DMAR code remains |
| 1914 | experimental. | 1914 | experimental. |
| 1915 | 1915 | ||
| 1916 | config DMAR_GFX_WA | ||
| 1917 | def_bool y | ||
| 1918 | prompt "Support for Graphics workaround" | ||
| 1919 | depends on DMAR | ||
| 1920 | ---help--- | ||
| 1921 | Current Graphics drivers tend to use physical address | ||
| 1922 | for DMA and avoid using DMA APIs. Setting this config | ||
| 1923 | option permits the IOMMU driver to set a unity map for | ||
| 1924 | all the OS-visible memory. Hence the driver can continue | ||
| 1925 | to use physical addresses for DMA. | ||
| 1926 | |||
| 1927 | config DMAR_FLOPPY_WA | 1916 | config DMAR_FLOPPY_WA |
| 1928 | def_bool y | 1917 | def_bool y |
| 1929 | depends on DMAR | 1918 | depends on DMAR |
| 1930 | ---help--- | 1919 | ---help--- |
| 1931 | Floppy disk drivers are know to bypass DMA API calls | 1920 | Floppy disk drivers are known to bypass DMA API calls |
| 1932 | thereby failing to work when IOMMU is enabled. This | 1921 | thereby failing to work when IOMMU is enabled. This |
| 1933 | workaround will setup a 1:1 mapping for the first | 1922 | workaround will setup a 1:1 mapping for the first |
| 1934 | 16M to make floppy (an ISA device) work. | 1923 | 16MiB to make floppy (an ISA device) work. |
| 1935 | 1924 | ||
| 1936 | config INTR_REMAP | 1925 | config INTR_REMAP |
| 1937 | bool "Support for Interrupt Remapping (EXPERIMENTAL)" | 1926 | bool "Support for Interrupt Remapping (EXPERIMENTAL)" |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 47630479b067..1a041bcf506b 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
| @@ -211,11 +211,11 @@ static __init int iommu_setup(char *p) | |||
| 211 | #ifdef CONFIG_SWIOTLB | 211 | #ifdef CONFIG_SWIOTLB |
| 212 | if (!strncmp(p, "soft", 4)) | 212 | if (!strncmp(p, "soft", 4)) |
| 213 | swiotlb = 1; | 213 | swiotlb = 1; |
| 214 | #endif | ||
| 214 | if (!strncmp(p, "pt", 2)) { | 215 | if (!strncmp(p, "pt", 2)) { |
| 215 | iommu_pass_through = 1; | 216 | iommu_pass_through = 1; |
| 216 | return 1; | 217 | return 1; |
| 217 | } | 218 | } |
| 218 | #endif | ||
| 219 | 219 | ||
| 220 | gart_parse_options(p); | 220 | gart_parse_options(p); |
| 221 | 221 | ||
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 420afa887283..53075424a434 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -56,14 +56,32 @@ | |||
| 56 | #define MAX_AGAW_WIDTH 64 | 56 | #define MAX_AGAW_WIDTH 64 |
| 57 | 57 | ||
| 58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) | 58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) |
| 59 | #define DOMAIN_MAX_PFN(gaw) ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1) | ||
| 59 | 60 | ||
| 60 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) | 61 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) |
| 61 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) | 62 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) |
| 62 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) | 63 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) |
| 63 | 64 | ||
| 64 | #ifndef PHYSICAL_PAGE_MASK | 65 | |
| 65 | #define PHYSICAL_PAGE_MASK PAGE_MASK | 66 | /* VT-d pages must always be _smaller_ than MM pages. Otherwise things |
| 66 | #endif | 67 | are never going to work. */ |
| 68 | static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn) | ||
| 69 | { | ||
| 70 | return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn) | ||
| 74 | { | ||
| 75 | return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
| 76 | } | ||
| 77 | static inline unsigned long page_to_dma_pfn(struct page *pg) | ||
| 78 | { | ||
| 79 | return mm_to_dma_pfn(page_to_pfn(pg)); | ||
| 80 | } | ||
| 81 | static inline unsigned long virt_to_dma_pfn(void *p) | ||
| 82 | { | ||
| 83 | return page_to_dma_pfn(virt_to_page(p)); | ||
| 84 | } | ||
| 67 | 85 | ||
| 68 | /* global iommu list, set NULL for ignored DMAR units */ | 86 | /* global iommu list, set NULL for ignored DMAR units */ |
| 69 | static struct intel_iommu **g_iommus; | 87 | static struct intel_iommu **g_iommus; |
| @@ -204,12 +222,17 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot) | |||
| 204 | 222 | ||
| 205 | static inline u64 dma_pte_addr(struct dma_pte *pte) | 223 | static inline u64 dma_pte_addr(struct dma_pte *pte) |
| 206 | { | 224 | { |
| 207 | return (pte->val & VTD_PAGE_MASK); | 225 | #ifdef CONFIG_64BIT |
| 226 | return pte->val & VTD_PAGE_MASK; | ||
| 227 | #else | ||
| 228 | /* Must have a full atomic 64-bit read */ | ||
| 229 | return __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK; | ||
| 230 | #endif | ||
| 208 | } | 231 | } |
| 209 | 232 | ||
| 210 | static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr) | 233 | static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn) |
| 211 | { | 234 | { |
| 212 | pte->val |= (addr & VTD_PAGE_MASK); | 235 | pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT; |
| 213 | } | 236 | } |
| 214 | 237 | ||
| 215 | static inline bool dma_pte_present(struct dma_pte *pte) | 238 | static inline bool dma_pte_present(struct dma_pte *pte) |
| @@ -217,6 +240,11 @@ static inline bool dma_pte_present(struct dma_pte *pte) | |||
| 217 | return (pte->val & 3) != 0; | 240 | return (pte->val & 3) != 0; |
| 218 | } | 241 | } |
| 219 | 242 | ||
| 243 | static inline int first_pte_in_page(struct dma_pte *pte) | ||
| 244 | { | ||
| 245 | return !((unsigned long)pte & ~VTD_PAGE_MASK); | ||
| 246 | } | ||
| 247 | |||
| 220 | /* | 248 | /* |
| 221 | * This domain is a statically identity mapping domain. | 249 | * This domain is a statically identity mapping domain. |
| 222 | * 1. This domain creats a static 1:1 mapping to all usable memory. | 250 | * 1. This domain creats a static 1:1 mapping to all usable memory. |
| @@ -244,7 +272,6 @@ struct dmar_domain { | |||
| 244 | struct iova_domain iovad; /* iova's that belong to this domain */ | 272 | struct iova_domain iovad; /* iova's that belong to this domain */ |
| 245 | 273 | ||
| 246 | struct dma_pte *pgd; /* virtual address */ | 274 | struct dma_pte *pgd; /* virtual address */ |
| 247 | spinlock_t mapping_lock; /* page table lock */ | ||
| 248 | int gaw; /* max guest address width */ | 275 | int gaw; /* max guest address width */ |
| 249 | 276 | ||
| 250 | /* adjusted guest address width, 0 is level 2 30-bit */ | 277 | /* adjusted guest address width, 0 is level 2 30-bit */ |
| @@ -648,80 +675,78 @@ static inline int width_to_agaw(int width) | |||
| 648 | 675 | ||
| 649 | static inline unsigned int level_to_offset_bits(int level) | 676 | static inline unsigned int level_to_offset_bits(int level) |
| 650 | { | 677 | { |
| 651 | return (12 + (level - 1) * LEVEL_STRIDE); | 678 | return (level - 1) * LEVEL_STRIDE; |
| 652 | } | 679 | } |
| 653 | 680 | ||
| 654 | static inline int address_level_offset(u64 addr, int level) | 681 | static inline int pfn_level_offset(unsigned long pfn, int level) |
| 655 | { | 682 | { |
| 656 | return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK); | 683 | return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; |
| 657 | } | 684 | } |
| 658 | 685 | ||
| 659 | static inline u64 level_mask(int level) | 686 | static inline unsigned long level_mask(int level) |
| 660 | { | 687 | { |
| 661 | return ((u64)-1 << level_to_offset_bits(level)); | 688 | return -1UL << level_to_offset_bits(level); |
| 662 | } | 689 | } |
| 663 | 690 | ||
| 664 | static inline u64 level_size(int level) | 691 | static inline unsigned long level_size(int level) |
| 665 | { | 692 | { |
| 666 | return ((u64)1 << level_to_offset_bits(level)); | 693 | return 1UL << level_to_offset_bits(level); |
| 667 | } | 694 | } |
| 668 | 695 | ||
| 669 | static inline u64 align_to_level(u64 addr, int level) | 696 | static inline unsigned long align_to_level(unsigned long pfn, int level) |
| 670 | { | 697 | { |
| 671 | return ((addr + level_size(level) - 1) & level_mask(level)); | 698 | return (pfn + level_size(level) - 1) & level_mask(level); |
| 672 | } | 699 | } |
| 673 | 700 | ||
| 674 | static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) | 701 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, |
| 702 | unsigned long pfn) | ||
| 675 | { | 703 | { |
| 676 | int addr_width = agaw_to_width(domain->agaw); | 704 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 677 | struct dma_pte *parent, *pte = NULL; | 705 | struct dma_pte *parent, *pte = NULL; |
| 678 | int level = agaw_to_level(domain->agaw); | 706 | int level = agaw_to_level(domain->agaw); |
| 679 | int offset; | 707 | int offset; |
| 680 | unsigned long flags; | ||
| 681 | 708 | ||
| 682 | BUG_ON(!domain->pgd); | 709 | BUG_ON(!domain->pgd); |
| 683 | 710 | BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); | |
| 684 | addr &= (((u64)1) << addr_width) - 1; | ||
| 685 | parent = domain->pgd; | 711 | parent = domain->pgd; |
| 686 | 712 | ||
| 687 | spin_lock_irqsave(&domain->mapping_lock, flags); | ||
| 688 | while (level > 0) { | 713 | while (level > 0) { |
| 689 | void *tmp_page; | 714 | void *tmp_page; |
| 690 | 715 | ||
| 691 | offset = address_level_offset(addr, level); | 716 | offset = pfn_level_offset(pfn, level); |
| 692 | pte = &parent[offset]; | 717 | pte = &parent[offset]; |
| 693 | if (level == 1) | 718 | if (level == 1) |
| 694 | break; | 719 | break; |
| 695 | 720 | ||
| 696 | if (!dma_pte_present(pte)) { | 721 | if (!dma_pte_present(pte)) { |
| 722 | uint64_t pteval; | ||
| 723 | |||
| 697 | tmp_page = alloc_pgtable_page(); | 724 | tmp_page = alloc_pgtable_page(); |
| 698 | 725 | ||
| 699 | if (!tmp_page) { | 726 | if (!tmp_page) |
| 700 | spin_unlock_irqrestore(&domain->mapping_lock, | ||
| 701 | flags); | ||
| 702 | return NULL; | 727 | return NULL; |
| 728 | |||
| 729 | domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); | ||
| 730 | pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; | ||
| 731 | if (cmpxchg64(&pte->val, 0ULL, pteval)) { | ||
| 732 | /* Someone else set it while we were thinking; use theirs. */ | ||
| 733 | free_pgtable_page(tmp_page); | ||
| 734 | } else { | ||
| 735 | dma_pte_addr(pte); | ||
| 736 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 703 | } | 737 | } |
| 704 | domain_flush_cache(domain, tmp_page, PAGE_SIZE); | ||
| 705 | dma_set_pte_addr(pte, virt_to_phys(tmp_page)); | ||
| 706 | /* | ||
| 707 | * high level table always sets r/w, last level page | ||
| 708 | * table control read/write | ||
| 709 | */ | ||
| 710 | dma_set_pte_readable(pte); | ||
| 711 | dma_set_pte_writable(pte); | ||
| 712 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 713 | } | 738 | } |
| 714 | parent = phys_to_virt(dma_pte_addr(pte)); | 739 | parent = phys_to_virt(dma_pte_addr(pte)); |
| 715 | level--; | 740 | level--; |
| 716 | } | 741 | } |
| 717 | 742 | ||
| 718 | spin_unlock_irqrestore(&domain->mapping_lock, flags); | ||
| 719 | return pte; | 743 | return pte; |
| 720 | } | 744 | } |
| 721 | 745 | ||
| 722 | /* return address's pte at specific level */ | 746 | /* return address's pte at specific level */ |
| 723 | static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | 747 | static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, |
| 724 | int level) | 748 | unsigned long pfn, |
| 749 | int level) | ||
| 725 | { | 750 | { |
| 726 | struct dma_pte *parent, *pte = NULL; | 751 | struct dma_pte *parent, *pte = NULL; |
| 727 | int total = agaw_to_level(domain->agaw); | 752 | int total = agaw_to_level(domain->agaw); |
| @@ -729,7 +754,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
| 729 | 754 | ||
| 730 | parent = domain->pgd; | 755 | parent = domain->pgd; |
| 731 | while (level <= total) { | 756 | while (level <= total) { |
| 732 | offset = address_level_offset(addr, total); | 757 | offset = pfn_level_offset(pfn, total); |
| 733 | pte = &parent[offset]; | 758 | pte = &parent[offset]; |
| 734 | if (level == total) | 759 | if (level == total) |
| 735 | return pte; | 760 | return pte; |
| @@ -742,74 +767,82 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
| 742 | return NULL; | 767 | return NULL; |
| 743 | } | 768 | } |
| 744 | 769 | ||
| 745 | /* clear one page's page table */ | ||
| 746 | static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) | ||
| 747 | { | ||
| 748 | struct dma_pte *pte = NULL; | ||
| 749 | |||
| 750 | /* get last level pte */ | ||
| 751 | pte = dma_addr_level_pte(domain, addr, 1); | ||
| 752 | |||
| 753 | if (pte) { | ||
| 754 | dma_clear_pte(pte); | ||
| 755 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 756 | } | ||
| 757 | } | ||
| 758 | |||
| 759 | /* clear last level pte, a tlb flush should be followed */ | 770 | /* clear last level pte, a tlb flush should be followed */ |
| 760 | static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) | 771 | static void dma_pte_clear_range(struct dmar_domain *domain, |
| 772 | unsigned long start_pfn, | ||
| 773 | unsigned long last_pfn) | ||
| 761 | { | 774 | { |
| 762 | int addr_width = agaw_to_width(domain->agaw); | 775 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 763 | int npages; | 776 | struct dma_pte *first_pte, *pte; |
| 777 | |||
| 778 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); | ||
| 779 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); | ||
| 764 | 780 | ||
| 765 | start &= (((u64)1) << addr_width) - 1; | 781 | /* we don't need lock here; nobody else touches the iova range */ |
| 766 | end &= (((u64)1) << addr_width) - 1; | 782 | while (start_pfn <= last_pfn) { |
| 767 | /* in case it's partial page */ | 783 | first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1); |
| 768 | start &= PAGE_MASK; | 784 | if (!pte) { |
| 769 | end = PAGE_ALIGN(end); | 785 | start_pfn = align_to_level(start_pfn + 1, 2); |
| 770 | npages = (end - start) / VTD_PAGE_SIZE; | 786 | continue; |
| 787 | } | ||
| 788 | do { | ||
| 789 | dma_clear_pte(pte); | ||
| 790 | start_pfn++; | ||
| 791 | pte++; | ||
| 792 | } while (start_pfn <= last_pfn && !first_pte_in_page(pte)); | ||
| 771 | 793 | ||
| 772 | /* we don't need lock here, nobody else touches the iova range */ | 794 | domain_flush_cache(domain, first_pte, |
| 773 | while (npages--) { | 795 | (void *)pte - (void *)first_pte); |
| 774 | dma_pte_clear_one(domain, start); | ||
| 775 | start += VTD_PAGE_SIZE; | ||
| 776 | } | 796 | } |
| 777 | } | 797 | } |
| 778 | 798 | ||
| 779 | /* free page table pages. last level pte should already be cleared */ | 799 | /* free page table pages. last level pte should already be cleared */ |
| 780 | static void dma_pte_free_pagetable(struct dmar_domain *domain, | 800 | static void dma_pte_free_pagetable(struct dmar_domain *domain, |
| 781 | u64 start, u64 end) | 801 | unsigned long start_pfn, |
| 802 | unsigned long last_pfn) | ||
| 782 | { | 803 | { |
| 783 | int addr_width = agaw_to_width(domain->agaw); | 804 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 784 | struct dma_pte *pte; | 805 | struct dma_pte *first_pte, *pte; |
| 785 | int total = agaw_to_level(domain->agaw); | 806 | int total = agaw_to_level(domain->agaw); |
| 786 | int level; | 807 | int level; |
| 787 | u64 tmp; | 808 | unsigned long tmp; |
| 788 | 809 | ||
| 789 | start &= (((u64)1) << addr_width) - 1; | 810 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); |
| 790 | end &= (((u64)1) << addr_width) - 1; | 811 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); |
| 791 | 812 | ||
| 792 | /* we don't need lock here, nobody else touches the iova range */ | 813 | /* We don't need lock here; nobody else touches the iova range */ |
| 793 | level = 2; | 814 | level = 2; |
| 794 | while (level <= total) { | 815 | while (level <= total) { |
| 795 | tmp = align_to_level(start, level); | 816 | tmp = align_to_level(start_pfn, level); |
| 796 | if (tmp >= end || (tmp + level_size(level) > end)) | 817 | |
| 818 | /* If we can't even clear one PTE at this level, we're done */ | ||
| 819 | if (tmp + level_size(level) - 1 > last_pfn) | ||
| 797 | return; | 820 | return; |
| 798 | 821 | ||
| 799 | while (tmp < end) { | 822 | while (tmp + level_size(level) - 1 <= last_pfn) { |
| 800 | pte = dma_addr_level_pte(domain, tmp, level); | 823 | first_pte = pte = dma_pfn_level_pte(domain, tmp, level); |
| 801 | if (pte) { | 824 | if (!pte) { |
| 802 | free_pgtable_page( | 825 | tmp = align_to_level(tmp + 1, level + 1); |
| 803 | phys_to_virt(dma_pte_addr(pte))); | 826 | continue; |
| 804 | dma_clear_pte(pte); | ||
| 805 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 806 | } | 827 | } |
| 807 | tmp += level_size(level); | 828 | do { |
| 829 | if (dma_pte_present(pte)) { | ||
| 830 | free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); | ||
| 831 | dma_clear_pte(pte); | ||
| 832 | } | ||
| 833 | pte++; | ||
| 834 | tmp += level_size(level); | ||
| 835 | } while (!first_pte_in_page(pte) && | ||
| 836 | tmp + level_size(level) - 1 <= last_pfn); | ||
| 837 | |||
| 838 | domain_flush_cache(domain, first_pte, | ||
| 839 | (void *)pte - (void *)first_pte); | ||
| 840 | |||
| 808 | } | 841 | } |
| 809 | level++; | 842 | level++; |
| 810 | } | 843 | } |
| 811 | /* free pgd */ | 844 | /* free pgd */ |
| 812 | if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) { | 845 | if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { |
| 813 | free_pgtable_page(domain->pgd); | 846 | free_pgtable_page(domain->pgd); |
| 814 | domain->pgd = NULL; | 847 | domain->pgd = NULL; |
| 815 | } | 848 | } |
| @@ -1035,11 +1068,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, | |||
| 1035 | } | 1068 | } |
| 1036 | 1069 | ||
| 1037 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | 1070 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, |
| 1038 | u64 addr, unsigned int pages) | 1071 | unsigned long pfn, unsigned int pages) |
| 1039 | { | 1072 | { |
| 1040 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); | 1073 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); |
| 1074 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; | ||
| 1041 | 1075 | ||
| 1042 | BUG_ON(addr & (~VTD_PAGE_MASK)); | ||
| 1043 | BUG_ON(pages == 0); | 1076 | BUG_ON(pages == 0); |
| 1044 | 1077 | ||
| 1045 | /* | 1078 | /* |
| @@ -1054,7 +1087,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
| 1054 | else | 1087 | else |
| 1055 | iommu->flush.flush_iotlb(iommu, did, addr, mask, | 1088 | iommu->flush.flush_iotlb(iommu, did, addr, mask, |
| 1056 | DMA_TLB_PSI_FLUSH); | 1089 | DMA_TLB_PSI_FLUSH); |
| 1057 | if (did) | 1090 | |
| 1091 | /* | ||
| 1092 | * In caching mode, domain ID 0 is reserved for non-present to present | ||
| 1093 | * mapping flush. Device IOTLB doesn't need to be flushed in this case. | ||
| 1094 | */ | ||
| 1095 | if (!cap_caching_mode(iommu->cap) || did) | ||
| 1058 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); | 1096 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); |
| 1059 | } | 1097 | } |
| 1060 | 1098 | ||
| @@ -1279,7 +1317,6 @@ static void dmar_init_reserved_ranges(void) | |||
| 1279 | struct pci_dev *pdev = NULL; | 1317 | struct pci_dev *pdev = NULL; |
| 1280 | struct iova *iova; | 1318 | struct iova *iova; |
| 1281 | int i; | 1319 | int i; |
| 1282 | u64 addr, size; | ||
| 1283 | 1320 | ||
| 1284 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); | 1321 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
| 1285 | 1322 | ||
| @@ -1302,12 +1339,9 @@ static void dmar_init_reserved_ranges(void) | |||
| 1302 | r = &pdev->resource[i]; | 1339 | r = &pdev->resource[i]; |
| 1303 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) | 1340 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) |
| 1304 | continue; | 1341 | continue; |
| 1305 | addr = r->start; | 1342 | iova = reserve_iova(&reserved_iova_list, |
| 1306 | addr &= PHYSICAL_PAGE_MASK; | 1343 | IOVA_PFN(r->start), |
| 1307 | size = r->end - addr; | 1344 | IOVA_PFN(r->end)); |
| 1308 | size = PAGE_ALIGN(size); | ||
| 1309 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), | ||
| 1310 | IOVA_PFN(size + addr) - 1); | ||
| 1311 | if (!iova) | 1345 | if (!iova) |
| 1312 | printk(KERN_ERR "Reserve iova failed\n"); | 1346 | printk(KERN_ERR "Reserve iova failed\n"); |
| 1313 | } | 1347 | } |
| @@ -1341,7 +1375,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
| 1341 | unsigned long sagaw; | 1375 | unsigned long sagaw; |
| 1342 | 1376 | ||
| 1343 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 1377 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
| 1344 | spin_lock_init(&domain->mapping_lock); | ||
| 1345 | spin_lock_init(&domain->iommu_lock); | 1378 | spin_lock_init(&domain->iommu_lock); |
| 1346 | 1379 | ||
| 1347 | domain_reserve_special_ranges(domain); | 1380 | domain_reserve_special_ranges(domain); |
| @@ -1388,7 +1421,6 @@ static void domain_exit(struct dmar_domain *domain) | |||
| 1388 | { | 1421 | { |
| 1389 | struct dmar_drhd_unit *drhd; | 1422 | struct dmar_drhd_unit *drhd; |
| 1390 | struct intel_iommu *iommu; | 1423 | struct intel_iommu *iommu; |
| 1391 | u64 end; | ||
| 1392 | 1424 | ||
| 1393 | /* Domain 0 is reserved, so dont process it */ | 1425 | /* Domain 0 is reserved, so dont process it */ |
| 1394 | if (!domain) | 1426 | if (!domain) |
| @@ -1397,14 +1429,12 @@ static void domain_exit(struct dmar_domain *domain) | |||
| 1397 | domain_remove_dev_info(domain); | 1429 | domain_remove_dev_info(domain); |
| 1398 | /* destroy iovas */ | 1430 | /* destroy iovas */ |
| 1399 | put_iova_domain(&domain->iovad); | 1431 | put_iova_domain(&domain->iovad); |
| 1400 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
| 1401 | end = end & (~PAGE_MASK); | ||
| 1402 | 1432 | ||
| 1403 | /* clear ptes */ | 1433 | /* clear ptes */ |
| 1404 | dma_pte_clear_range(domain, 0, end); | 1434 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 1405 | 1435 | ||
| 1406 | /* free page tables */ | 1436 | /* free page tables */ |
| 1407 | dma_pte_free_pagetable(domain, 0, end); | 1437 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 1408 | 1438 | ||
| 1409 | for_each_active_iommu(iommu, drhd) | 1439 | for_each_active_iommu(iommu, drhd) |
| 1410 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) | 1440 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) |
| @@ -1618,42 +1648,86 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
| 1618 | tmp->devfn); | 1648 | tmp->devfn); |
| 1619 | } | 1649 | } |
| 1620 | 1650 | ||
| 1621 | static int | 1651 | static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
| 1622 | domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, | 1652 | struct scatterlist *sg, unsigned long phys_pfn, |
| 1623 | u64 hpa, size_t size, int prot) | 1653 | unsigned long nr_pages, int prot) |
| 1624 | { | 1654 | { |
| 1625 | u64 start_pfn, end_pfn; | 1655 | struct dma_pte *first_pte = NULL, *pte = NULL; |
| 1626 | struct dma_pte *pte; | 1656 | phys_addr_t uninitialized_var(pteval); |
| 1627 | int index; | 1657 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 1628 | int addr_width = agaw_to_width(domain->agaw); | 1658 | unsigned long sg_res; |
| 1629 | 1659 | ||
| 1630 | hpa &= (((u64)1) << addr_width) - 1; | 1660 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); |
| 1631 | 1661 | ||
| 1632 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) | 1662 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) |
| 1633 | return -EINVAL; | 1663 | return -EINVAL; |
| 1634 | iova &= PAGE_MASK; | 1664 | |
| 1635 | start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT; | 1665 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; |
| 1636 | end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; | 1666 | |
| 1637 | index = 0; | 1667 | if (sg) |
| 1638 | while (start_pfn < end_pfn) { | 1668 | sg_res = 0; |
| 1639 | pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index); | 1669 | else { |
| 1640 | if (!pte) | 1670 | sg_res = nr_pages + 1; |
| 1641 | return -ENOMEM; | 1671 | pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; |
| 1672 | } | ||
| 1673 | |||
| 1674 | while (nr_pages--) { | ||
| 1675 | uint64_t tmp; | ||
| 1676 | |||
| 1677 | if (!sg_res) { | ||
| 1678 | sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; | ||
| 1679 | sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; | ||
| 1680 | sg->dma_length = sg->length; | ||
| 1681 | pteval = page_to_phys(sg_page(sg)) | prot; | ||
| 1682 | } | ||
| 1683 | if (!pte) { | ||
| 1684 | first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); | ||
| 1685 | if (!pte) | ||
| 1686 | return -ENOMEM; | ||
| 1687 | } | ||
| 1642 | /* We don't need lock here, nobody else | 1688 | /* We don't need lock here, nobody else |
| 1643 | * touches the iova range | 1689 | * touches the iova range |
| 1644 | */ | 1690 | */ |
| 1645 | BUG_ON(dma_pte_addr(pte)); | 1691 | tmp = cmpxchg64_local(&pte->val, 0ULL, pteval); |
| 1646 | dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT); | 1692 | if (tmp) { |
| 1647 | dma_set_pte_prot(pte, prot); | 1693 | static int dumps = 5; |
| 1648 | if (prot & DMA_PTE_SNP) | 1694 | printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n", |
| 1649 | dma_set_pte_snp(pte); | 1695 | iov_pfn, tmp, (unsigned long long)pteval); |
| 1650 | domain_flush_cache(domain, pte, sizeof(*pte)); | 1696 | if (dumps) { |
| 1651 | start_pfn++; | 1697 | dumps--; |
| 1652 | index++; | 1698 | debug_dma_dump_mappings(NULL); |
| 1699 | } | ||
| 1700 | WARN_ON(1); | ||
| 1701 | } | ||
| 1702 | pte++; | ||
| 1703 | if (!nr_pages || first_pte_in_page(pte)) { | ||
| 1704 | domain_flush_cache(domain, first_pte, | ||
| 1705 | (void *)pte - (void *)first_pte); | ||
| 1706 | pte = NULL; | ||
| 1707 | } | ||
| 1708 | iov_pfn++; | ||
| 1709 | pteval += VTD_PAGE_SIZE; | ||
| 1710 | sg_res--; | ||
| 1711 | if (!sg_res) | ||
| 1712 | sg = sg_next(sg); | ||
| 1653 | } | 1713 | } |
| 1654 | return 0; | 1714 | return 0; |
| 1655 | } | 1715 | } |
| 1656 | 1716 | ||
| 1717 | static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
| 1718 | struct scatterlist *sg, unsigned long nr_pages, | ||
| 1719 | int prot) | ||
| 1720 | { | ||
| 1721 | return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot); | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
| 1725 | unsigned long phys_pfn, unsigned long nr_pages, | ||
| 1726 | int prot) | ||
| 1727 | { | ||
| 1728 | return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot); | ||
| 1729 | } | ||
| 1730 | |||
| 1657 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) | 1731 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) |
| 1658 | { | 1732 | { |
| 1659 | if (!iommu) | 1733 | if (!iommu) |
| @@ -1844,58 +1918,61 @@ error: | |||
| 1844 | 1918 | ||
| 1845 | static int iommu_identity_mapping; | 1919 | static int iommu_identity_mapping; |
| 1846 | 1920 | ||
| 1921 | static int iommu_domain_identity_map(struct dmar_domain *domain, | ||
| 1922 | unsigned long long start, | ||
| 1923 | unsigned long long end) | ||
| 1924 | { | ||
| 1925 | unsigned long first_vpfn = start >> VTD_PAGE_SHIFT; | ||
| 1926 | unsigned long last_vpfn = end >> VTD_PAGE_SHIFT; | ||
| 1927 | |||
| 1928 | if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn), | ||
| 1929 | dma_to_mm_pfn(last_vpfn))) { | ||
| 1930 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
| 1931 | return -ENOMEM; | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | pr_debug("Mapping reserved region %llx-%llx for domain %d\n", | ||
| 1935 | start, end, domain->id); | ||
| 1936 | /* | ||
| 1937 | * RMRR range might have overlap with physical memory range, | ||
| 1938 | * clear it first | ||
| 1939 | */ | ||
| 1940 | dma_pte_clear_range(domain, first_vpfn, last_vpfn); | ||
| 1941 | |||
| 1942 | return domain_pfn_mapping(domain, first_vpfn, first_vpfn, | ||
| 1943 | last_vpfn - first_vpfn + 1, | ||
| 1944 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
| 1945 | } | ||
| 1946 | |||
| 1847 | static int iommu_prepare_identity_map(struct pci_dev *pdev, | 1947 | static int iommu_prepare_identity_map(struct pci_dev *pdev, |
| 1848 | unsigned long long start, | 1948 | unsigned long long start, |
| 1849 | unsigned long long end) | 1949 | unsigned long long end) |
| 1850 | { | 1950 | { |
| 1851 | struct dmar_domain *domain; | 1951 | struct dmar_domain *domain; |
| 1852 | unsigned long size; | ||
| 1853 | unsigned long long base; | ||
| 1854 | int ret; | 1952 | int ret; |
| 1855 | 1953 | ||
| 1856 | printk(KERN_INFO | 1954 | printk(KERN_INFO |
| 1857 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 1955 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
| 1858 | pci_name(pdev), start, end); | 1956 | pci_name(pdev), start, end); |
| 1859 | if (iommu_identity_mapping) | 1957 | |
| 1860 | domain = si_domain; | 1958 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
| 1861 | else | ||
| 1862 | /* page table init */ | ||
| 1863 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | ||
| 1864 | if (!domain) | 1959 | if (!domain) |
| 1865 | return -ENOMEM; | 1960 | return -ENOMEM; |
| 1866 | 1961 | ||
| 1867 | /* The address might not be aligned */ | 1962 | ret = iommu_domain_identity_map(domain, start, end); |
| 1868 | base = start & PAGE_MASK; | ||
| 1869 | size = end - base; | ||
| 1870 | size = PAGE_ALIGN(size); | ||
| 1871 | if (!reserve_iova(&domain->iovad, IOVA_PFN(base), | ||
| 1872 | IOVA_PFN(base + size) - 1)) { | ||
| 1873 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
| 1874 | ret = -ENOMEM; | ||
| 1875 | goto error; | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | pr_debug("Mapping reserved region %lx@%llx for %s\n", | ||
| 1879 | size, base, pci_name(pdev)); | ||
| 1880 | /* | ||
| 1881 | * RMRR range might have overlap with physical memory range, | ||
| 1882 | * clear it first | ||
| 1883 | */ | ||
| 1884 | dma_pte_clear_range(domain, base, base + size); | ||
| 1885 | |||
| 1886 | ret = domain_page_mapping(domain, base, base, size, | ||
| 1887 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
| 1888 | if (ret) | 1963 | if (ret) |
| 1889 | goto error; | 1964 | goto error; |
| 1890 | 1965 | ||
| 1891 | /* context entry init */ | 1966 | /* context entry init */ |
| 1892 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); | 1967 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); |
| 1893 | if (!ret) | 1968 | if (ret) |
| 1894 | return 0; | 1969 | goto error; |
| 1895 | error: | 1970 | |
| 1971 | return 0; | ||
| 1972 | |||
| 1973 | error: | ||
| 1896 | domain_exit(domain); | 1974 | domain_exit(domain); |
| 1897 | return ret; | 1975 | return ret; |
| 1898 | |||
| 1899 | } | 1976 | } |
| 1900 | 1977 | ||
| 1901 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | 1978 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, |
| @@ -1907,64 +1984,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | |||
| 1907 | rmrr->end_address + 1); | 1984 | rmrr->end_address + 1); |
| 1908 | } | 1985 | } |
| 1909 | 1986 | ||
| 1910 | struct iommu_prepare_data { | ||
| 1911 | struct pci_dev *pdev; | ||
| 1912 | int ret; | ||
| 1913 | }; | ||
| 1914 | |||
| 1915 | static int __init iommu_prepare_work_fn(unsigned long start_pfn, | ||
| 1916 | unsigned long end_pfn, void *datax) | ||
| 1917 | { | ||
| 1918 | struct iommu_prepare_data *data; | ||
| 1919 | |||
| 1920 | data = (struct iommu_prepare_data *)datax; | ||
| 1921 | |||
| 1922 | data->ret = iommu_prepare_identity_map(data->pdev, | ||
| 1923 | start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
| 1924 | return data->ret; | ||
| 1925 | |||
| 1926 | } | ||
| 1927 | |||
| 1928 | static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) | ||
| 1929 | { | ||
| 1930 | int nid; | ||
| 1931 | struct iommu_prepare_data data; | ||
| 1932 | |||
| 1933 | data.pdev = pdev; | ||
| 1934 | data.ret = 0; | ||
| 1935 | |||
| 1936 | for_each_online_node(nid) { | ||
| 1937 | work_with_active_regions(nid, iommu_prepare_work_fn, &data); | ||
| 1938 | if (data.ret) | ||
| 1939 | return data.ret; | ||
| 1940 | } | ||
| 1941 | return data.ret; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | #ifdef CONFIG_DMAR_GFX_WA | ||
| 1945 | static void __init iommu_prepare_gfx_mapping(void) | ||
| 1946 | { | ||
| 1947 | struct pci_dev *pdev = NULL; | ||
| 1948 | int ret; | ||
| 1949 | |||
| 1950 | for_each_pci_dev(pdev) { | ||
| 1951 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || | ||
| 1952 | !IS_GFX_DEVICE(pdev)) | ||
| 1953 | continue; | ||
| 1954 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | ||
| 1955 | pci_name(pdev)); | ||
| 1956 | ret = iommu_prepare_with_active_regions(pdev); | ||
| 1957 | if (ret) | ||
| 1958 | printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | ||
| 1959 | } | ||
| 1960 | } | ||
| 1961 | #else /* !CONFIG_DMAR_GFX_WA */ | ||
| 1962 | static inline void iommu_prepare_gfx_mapping(void) | ||
| 1963 | { | ||
| 1964 | return; | ||
| 1965 | } | ||
| 1966 | #endif | ||
| 1967 | |||
| 1968 | #ifdef CONFIG_DMAR_FLOPPY_WA | 1987 | #ifdef CONFIG_DMAR_FLOPPY_WA |
| 1969 | static inline void iommu_prepare_isa(void) | 1988 | static inline void iommu_prepare_isa(void) |
| 1970 | { | 1989 | { |
| @@ -1975,12 +1994,12 @@ static inline void iommu_prepare_isa(void) | |||
| 1975 | if (!pdev) | 1994 | if (!pdev) |
| 1976 | return; | 1995 | return; |
| 1977 | 1996 | ||
| 1978 | printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); | 1997 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); |
| 1979 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); | 1998 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
| 1980 | 1999 | ||
| 1981 | if (ret) | 2000 | if (ret) |
| 1982 | printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " | 2001 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " |
| 1983 | "floppy might not work\n"); | 2002 | "floppy might not work\n"); |
| 1984 | 2003 | ||
| 1985 | } | 2004 | } |
| 1986 | #else | 2005 | #else |
| @@ -2008,16 +2027,30 @@ static int __init init_context_pass_through(void) | |||
| 2008 | } | 2027 | } |
| 2009 | 2028 | ||
| 2010 | static int md_domain_init(struct dmar_domain *domain, int guest_width); | 2029 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
| 2030 | |||
| 2031 | static int __init si_domain_work_fn(unsigned long start_pfn, | ||
| 2032 | unsigned long end_pfn, void *datax) | ||
| 2033 | { | ||
| 2034 | int *ret = datax; | ||
| 2035 | |||
| 2036 | *ret = iommu_domain_identity_map(si_domain, | ||
| 2037 | (uint64_t)start_pfn << PAGE_SHIFT, | ||
| 2038 | (uint64_t)end_pfn << PAGE_SHIFT); | ||
| 2039 | return *ret; | ||
| 2040 | |||
| 2041 | } | ||
| 2042 | |||
| 2011 | static int si_domain_init(void) | 2043 | static int si_domain_init(void) |
| 2012 | { | 2044 | { |
| 2013 | struct dmar_drhd_unit *drhd; | 2045 | struct dmar_drhd_unit *drhd; |
| 2014 | struct intel_iommu *iommu; | 2046 | struct intel_iommu *iommu; |
| 2015 | int ret = 0; | 2047 | int nid, ret = 0; |
| 2016 | 2048 | ||
| 2017 | si_domain = alloc_domain(); | 2049 | si_domain = alloc_domain(); |
| 2018 | if (!si_domain) | 2050 | if (!si_domain) |
| 2019 | return -EFAULT; | 2051 | return -EFAULT; |
| 2020 | 2052 | ||
| 2053 | pr_debug("Identity mapping domain is domain %d\n", si_domain->id); | ||
| 2021 | 2054 | ||
| 2022 | for_each_active_iommu(iommu, drhd) { | 2055 | for_each_active_iommu(iommu, drhd) { |
| 2023 | ret = iommu_attach_domain(si_domain, iommu); | 2056 | ret = iommu_attach_domain(si_domain, iommu); |
| @@ -2034,6 +2067,12 @@ static int si_domain_init(void) | |||
| 2034 | 2067 | ||
| 2035 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | 2068 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; |
| 2036 | 2069 | ||
| 2070 | for_each_online_node(nid) { | ||
| 2071 | work_with_active_regions(nid, si_domain_work_fn, &ret); | ||
| 2072 | if (ret) | ||
| 2073 | return ret; | ||
| 2074 | } | ||
| 2075 | |||
| 2037 | return 0; | 2076 | return 0; |
| 2038 | } | 2077 | } |
| 2039 | 2078 | ||
| @@ -2087,13 +2126,14 @@ static int iommu_prepare_static_identity_mapping(void) | |||
| 2087 | if (ret) | 2126 | if (ret) |
| 2088 | return -EFAULT; | 2127 | return -EFAULT; |
| 2089 | 2128 | ||
| 2090 | printk(KERN_INFO "IOMMU: Setting identity map:\n"); | ||
| 2091 | for_each_pci_dev(pdev) { | 2129 | for_each_pci_dev(pdev) { |
| 2092 | ret = iommu_prepare_with_active_regions(pdev); | 2130 | printk(KERN_INFO "IOMMU: identity mapping for device %s\n", |
| 2093 | if (ret) { | 2131 | pci_name(pdev)); |
| 2094 | printk(KERN_INFO "1:1 mapping to one domain failed.\n"); | 2132 | |
| 2095 | return -EFAULT; | 2133 | ret = domain_context_mapping(si_domain, pdev, |
| 2096 | } | 2134 | CONTEXT_TT_MULTI_LEVEL); |
| 2135 | if (ret) | ||
| 2136 | return ret; | ||
| 2097 | ret = domain_add_dev_info(si_domain, pdev); | 2137 | ret = domain_add_dev_info(si_domain, pdev); |
| 2098 | if (ret) | 2138 | if (ret) |
| 2099 | return ret; | 2139 | return ret; |
| @@ -2284,8 +2324,6 @@ int __init init_dmars(void) | |||
| 2284 | } | 2324 | } |
| 2285 | } | 2325 | } |
| 2286 | 2326 | ||
| 2287 | iommu_prepare_gfx_mapping(); | ||
| 2288 | |||
| 2289 | iommu_prepare_isa(); | 2327 | iommu_prepare_isa(); |
| 2290 | } | 2328 | } |
| 2291 | 2329 | ||
| @@ -2330,50 +2368,40 @@ error: | |||
| 2330 | return ret; | 2368 | return ret; |
| 2331 | } | 2369 | } |
| 2332 | 2370 | ||
| 2333 | static inline u64 aligned_size(u64 host_addr, size_t size) | 2371 | static inline unsigned long aligned_nrpages(unsigned long host_addr, |
| 2334 | { | 2372 | size_t size) |
| 2335 | u64 addr; | ||
| 2336 | addr = (host_addr & (~PAGE_MASK)) + size; | ||
| 2337 | return PAGE_ALIGN(addr); | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | struct iova * | ||
| 2341 | iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) | ||
| 2342 | { | 2373 | { |
| 2343 | struct iova *piova; | 2374 | host_addr &= ~PAGE_MASK; |
| 2375 | host_addr += size + PAGE_SIZE - 1; | ||
| 2344 | 2376 | ||
| 2345 | /* Make sure it's in range */ | 2377 | return host_addr >> VTD_PAGE_SHIFT; |
| 2346 | end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); | ||
| 2347 | if (!size || (IOVA_START_ADDR + size > end)) | ||
| 2348 | return NULL; | ||
| 2349 | |||
| 2350 | piova = alloc_iova(&domain->iovad, | ||
| 2351 | size >> PAGE_SHIFT, IOVA_PFN(end), 1); | ||
| 2352 | return piova; | ||
| 2353 | } | 2378 | } |
| 2354 | 2379 | ||
| 2355 | static struct iova * | 2380 | static struct iova *intel_alloc_iova(struct device *dev, |
| 2356 | __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, | 2381 | struct dmar_domain *domain, |
| 2357 | size_t size, u64 dma_mask) | 2382 | unsigned long nrpages, uint64_t dma_mask) |
| 2358 | { | 2383 | { |
| 2359 | struct pci_dev *pdev = to_pci_dev(dev); | 2384 | struct pci_dev *pdev = to_pci_dev(dev); |
| 2360 | struct iova *iova = NULL; | 2385 | struct iova *iova = NULL; |
| 2361 | 2386 | ||
| 2362 | if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac) | 2387 | /* Restrict dma_mask to the width that the iommu can handle */ |
| 2363 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2388 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); |
| 2364 | else { | 2389 | |
| 2390 | if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) { | ||
| 2365 | /* | 2391 | /* |
| 2366 | * First try to allocate an io virtual address in | 2392 | * First try to allocate an io virtual address in |
| 2367 | * DMA_BIT_MASK(32) and if that fails then try allocating | 2393 | * DMA_BIT_MASK(32) and if that fails then try allocating |
| 2368 | * from higher range | 2394 | * from higher range |
| 2369 | */ | 2395 | */ |
| 2370 | iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32)); | 2396 | iova = alloc_iova(&domain->iovad, nrpages, |
| 2371 | if (!iova) | 2397 | IOVA_PFN(DMA_BIT_MASK(32)), 1); |
| 2372 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2398 | if (iova) |
| 2373 | } | 2399 | return iova; |
| 2374 | 2400 | } | |
| 2375 | if (!iova) { | 2401 | iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); |
| 2376 | printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); | 2402 | if (unlikely(!iova)) { |
| 2403 | printk(KERN_ERR "Allocating %ld-page iova for %s failed", | ||
| 2404 | nrpages, pci_name(pdev)); | ||
| 2377 | return NULL; | 2405 | return NULL; |
| 2378 | } | 2406 | } |
| 2379 | 2407 | ||
| @@ -2476,14 +2504,12 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
| 2476 | return 0; | 2504 | return 0; |
| 2477 | 2505 | ||
| 2478 | iommu = domain_get_iommu(domain); | 2506 | iommu = domain_get_iommu(domain); |
| 2479 | size = aligned_size((u64)paddr, size); | 2507 | size = aligned_nrpages(paddr, size); |
| 2480 | 2508 | ||
| 2481 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2509 | iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); |
| 2482 | if (!iova) | 2510 | if (!iova) |
| 2483 | goto error; | 2511 | goto error; |
| 2484 | 2512 | ||
| 2485 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; | ||
| 2486 | |||
| 2487 | /* | 2513 | /* |
| 2488 | * Check if DMAR supports zero-length reads on write only | 2514 | * Check if DMAR supports zero-length reads on write only |
| 2489 | * mappings.. | 2515 | * mappings.. |
| @@ -2499,20 +2525,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
| 2499 | * might have two guest_addr mapping to the same host paddr, but this | 2525 | * might have two guest_addr mapping to the same host paddr, but this |
| 2500 | * is not a big problem | 2526 | * is not a big problem |
| 2501 | */ | 2527 | */ |
| 2502 | ret = domain_page_mapping(domain, start_paddr, | 2528 | ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo), |
| 2503 | ((u64)paddr) & PHYSICAL_PAGE_MASK, | 2529 | paddr >> VTD_PAGE_SHIFT, size, prot); |
| 2504 | size, prot); | ||
| 2505 | if (ret) | 2530 | if (ret) |
| 2506 | goto error; | 2531 | goto error; |
| 2507 | 2532 | ||
| 2508 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2533 | /* it's a non-present to present mapping. Only flush if caching mode */ |
| 2509 | if (cap_caching_mode(iommu->cap)) | 2534 | if (cap_caching_mode(iommu->cap)) |
| 2510 | iommu_flush_iotlb_psi(iommu, 0, start_paddr, | 2535 | iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size); |
| 2511 | size >> VTD_PAGE_SHIFT); | ||
| 2512 | else | 2536 | else |
| 2513 | iommu_flush_write_buffer(iommu); | 2537 | iommu_flush_write_buffer(iommu); |
| 2514 | 2538 | ||
| 2515 | return start_paddr + ((u64)paddr & (~PAGE_MASK)); | 2539 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; |
| 2540 | start_paddr += paddr & ~PAGE_MASK; | ||
| 2541 | return start_paddr; | ||
| 2516 | 2542 | ||
| 2517 | error: | 2543 | error: |
| 2518 | if (iova) | 2544 | if (iova) |
| @@ -2605,7 +2631,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
| 2605 | { | 2631 | { |
| 2606 | struct pci_dev *pdev = to_pci_dev(dev); | 2632 | struct pci_dev *pdev = to_pci_dev(dev); |
| 2607 | struct dmar_domain *domain; | 2633 | struct dmar_domain *domain; |
| 2608 | unsigned long start_addr; | 2634 | unsigned long start_pfn, last_pfn; |
| 2609 | struct iova *iova; | 2635 | struct iova *iova; |
| 2610 | struct intel_iommu *iommu; | 2636 | struct intel_iommu *iommu; |
| 2611 | 2637 | ||
| @@ -2618,22 +2644,25 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
| 2618 | iommu = domain_get_iommu(domain); | 2644 | iommu = domain_get_iommu(domain); |
| 2619 | 2645 | ||
| 2620 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); | 2646 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); |
| 2621 | if (!iova) | 2647 | if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n", |
| 2648 | (unsigned long long)dev_addr)) | ||
| 2622 | return; | 2649 | return; |
| 2623 | 2650 | ||
| 2624 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2651 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
| 2625 | size = aligned_size((u64)dev_addr, size); | 2652 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; |
| 2626 | 2653 | ||
| 2627 | pr_debug("Device %s unmapping: %zx@%llx\n", | 2654 | pr_debug("Device %s unmapping: pfn %lx-%lx\n", |
| 2628 | pci_name(pdev), size, (unsigned long long)start_addr); | 2655 | pci_name(pdev), start_pfn, last_pfn); |
| 2629 | 2656 | ||
| 2630 | /* clear the whole page */ | 2657 | /* clear the whole page */ |
| 2631 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2658 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
| 2659 | |||
| 2632 | /* free page tables */ | 2660 | /* free page tables */ |
| 2633 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2661 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
| 2662 | |||
| 2634 | if (intel_iommu_strict) { | 2663 | if (intel_iommu_strict) { |
| 2635 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2664 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
| 2636 | size >> VTD_PAGE_SHIFT); | 2665 | last_pfn - start_pfn + 1); |
| 2637 | /* free iova */ | 2666 | /* free iova */ |
| 2638 | __free_iova(&domain->iovad, iova); | 2667 | __free_iova(&domain->iovad, iova); |
| 2639 | } else { | 2668 | } else { |
| @@ -2691,14 +2720,10 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
| 2691 | int nelems, enum dma_data_direction dir, | 2720 | int nelems, enum dma_data_direction dir, |
| 2692 | struct dma_attrs *attrs) | 2721 | struct dma_attrs *attrs) |
| 2693 | { | 2722 | { |
| 2694 | int i; | ||
| 2695 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2723 | struct pci_dev *pdev = to_pci_dev(hwdev); |
| 2696 | struct dmar_domain *domain; | 2724 | struct dmar_domain *domain; |
| 2697 | unsigned long start_addr; | 2725 | unsigned long start_pfn, last_pfn; |
| 2698 | struct iova *iova; | 2726 | struct iova *iova; |
| 2699 | size_t size = 0; | ||
| 2700 | phys_addr_t addr; | ||
| 2701 | struct scatterlist *sg; | ||
| 2702 | struct intel_iommu *iommu; | 2727 | struct intel_iommu *iommu; |
| 2703 | 2728 | ||
| 2704 | if (iommu_no_mapping(pdev)) | 2729 | if (iommu_no_mapping(pdev)) |
| @@ -2710,22 +2735,21 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
| 2710 | iommu = domain_get_iommu(domain); | 2735 | iommu = domain_get_iommu(domain); |
| 2711 | 2736 | ||
| 2712 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); | 2737 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); |
| 2713 | if (!iova) | 2738 | if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n", |
| 2739 | (unsigned long long)sglist[0].dma_address)) | ||
| 2714 | return; | 2740 | return; |
| 2715 | for_each_sg(sglist, sg, nelems, i) { | ||
| 2716 | addr = page_to_phys(sg_page(sg)) + sg->offset; | ||
| 2717 | size += aligned_size((u64)addr, sg->length); | ||
| 2718 | } | ||
| 2719 | 2741 | ||
| 2720 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2742 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
| 2743 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; | ||
| 2721 | 2744 | ||
| 2722 | /* clear the whole page */ | 2745 | /* clear the whole page */ |
| 2723 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2746 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
| 2747 | |||
| 2724 | /* free page tables */ | 2748 | /* free page tables */ |
| 2725 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2749 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
| 2726 | 2750 | ||
| 2727 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2751 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
| 2728 | size >> VTD_PAGE_SHIFT); | 2752 | (last_pfn - start_pfn + 1)); |
| 2729 | 2753 | ||
| 2730 | /* free iova */ | 2754 | /* free iova */ |
| 2731 | __free_iova(&domain->iovad, iova); | 2755 | __free_iova(&domain->iovad, iova); |
| @@ -2748,17 +2772,16 @@ static int intel_nontranslate_map_sg(struct device *hddev, | |||
| 2748 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, | 2772 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, |
| 2749 | enum dma_data_direction dir, struct dma_attrs *attrs) | 2773 | enum dma_data_direction dir, struct dma_attrs *attrs) |
| 2750 | { | 2774 | { |
| 2751 | phys_addr_t addr; | ||
| 2752 | int i; | 2775 | int i; |
| 2753 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2776 | struct pci_dev *pdev = to_pci_dev(hwdev); |
| 2754 | struct dmar_domain *domain; | 2777 | struct dmar_domain *domain; |
| 2755 | size_t size = 0; | 2778 | size_t size = 0; |
| 2756 | int prot = 0; | 2779 | int prot = 0; |
| 2757 | size_t offset = 0; | 2780 | size_t offset_pfn = 0; |
| 2758 | struct iova *iova = NULL; | 2781 | struct iova *iova = NULL; |
| 2759 | int ret; | 2782 | int ret; |
| 2760 | struct scatterlist *sg; | 2783 | struct scatterlist *sg; |
| 2761 | unsigned long start_addr; | 2784 | unsigned long start_vpfn; |
| 2762 | struct intel_iommu *iommu; | 2785 | struct intel_iommu *iommu; |
| 2763 | 2786 | ||
| 2764 | BUG_ON(dir == DMA_NONE); | 2787 | BUG_ON(dir == DMA_NONE); |
| @@ -2771,12 +2794,10 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
| 2771 | 2794 | ||
| 2772 | iommu = domain_get_iommu(domain); | 2795 | iommu = domain_get_iommu(domain); |
| 2773 | 2796 | ||
| 2774 | for_each_sg(sglist, sg, nelems, i) { | 2797 | for_each_sg(sglist, sg, nelems, i) |
| 2775 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2798 | size += aligned_nrpages(sg->offset, sg->length); |
| 2776 | size += aligned_size((u64)addr, sg->length); | ||
| 2777 | } | ||
| 2778 | 2799 | ||
| 2779 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2800 | iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); |
| 2780 | if (!iova) { | 2801 | if (!iova) { |
| 2781 | sglist->dma_length = 0; | 2802 | sglist->dma_length = 0; |
| 2782 | return 0; | 2803 | return 0; |
| @@ -2792,35 +2813,24 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
| 2792 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) | 2813 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) |
| 2793 | prot |= DMA_PTE_WRITE; | 2814 | prot |= DMA_PTE_WRITE; |
| 2794 | 2815 | ||
| 2795 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2816 | start_vpfn = mm_to_dma_pfn(iova->pfn_lo); |
| 2796 | offset = 0; | 2817 | |
| 2797 | for_each_sg(sglist, sg, nelems, i) { | 2818 | ret = domain_sg_mapping(domain, start_vpfn, sglist, mm_to_dma_pfn(size), prot); |
| 2798 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2819 | if (unlikely(ret)) { |
| 2799 | size = aligned_size((u64)addr, sg->length); | 2820 | /* clear the page */ |
| 2800 | ret = domain_page_mapping(domain, start_addr + offset, | 2821 | dma_pte_clear_range(domain, start_vpfn, |
| 2801 | ((u64)addr) & PHYSICAL_PAGE_MASK, | 2822 | start_vpfn + size - 1); |
| 2802 | size, prot); | 2823 | /* free page tables */ |
| 2803 | if (ret) { | 2824 | dma_pte_free_pagetable(domain, start_vpfn, |
| 2804 | /* clear the page */ | 2825 | start_vpfn + size - 1); |
| 2805 | dma_pte_clear_range(domain, start_addr, | 2826 | /* free iova */ |
| 2806 | start_addr + offset); | 2827 | __free_iova(&domain->iovad, iova); |
| 2807 | /* free page tables */ | 2828 | return 0; |
| 2808 | dma_pte_free_pagetable(domain, start_addr, | ||
| 2809 | start_addr + offset); | ||
| 2810 | /* free iova */ | ||
| 2811 | __free_iova(&domain->iovad, iova); | ||
| 2812 | return 0; | ||
| 2813 | } | ||
| 2814 | sg->dma_address = start_addr + offset + | ||
| 2815 | ((u64)addr & (~PAGE_MASK)); | ||
| 2816 | sg->dma_length = sg->length; | ||
| 2817 | offset += size; | ||
| 2818 | } | 2829 | } |
| 2819 | 2830 | ||
| 2820 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2831 | /* it's a non-present to present mapping. Only flush if caching mode */ |
| 2821 | if (cap_caching_mode(iommu->cap)) | 2832 | if (cap_caching_mode(iommu->cap)) |
| 2822 | iommu_flush_iotlb_psi(iommu, 0, start_addr, | 2833 | iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn); |
| 2823 | offset >> VTD_PAGE_SHIFT); | ||
| 2824 | else | 2834 | else |
| 2825 | iommu_flush_write_buffer(iommu); | 2835 | iommu_flush_write_buffer(iommu); |
| 2826 | 2836 | ||
| @@ -3325,7 +3335,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) | |||
| 3325 | int adjust_width; | 3335 | int adjust_width; |
| 3326 | 3336 | ||
| 3327 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 3337 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
| 3328 | spin_lock_init(&domain->mapping_lock); | ||
| 3329 | spin_lock_init(&domain->iommu_lock); | 3338 | spin_lock_init(&domain->iommu_lock); |
| 3330 | 3339 | ||
| 3331 | domain_reserve_special_ranges(domain); | 3340 | domain_reserve_special_ranges(domain); |
| @@ -3379,8 +3388,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) | |||
| 3379 | 3388 | ||
| 3380 | static void vm_domain_exit(struct dmar_domain *domain) | 3389 | static void vm_domain_exit(struct dmar_domain *domain) |
| 3381 | { | 3390 | { |
| 3382 | u64 end; | ||
| 3383 | |||
| 3384 | /* Domain 0 is reserved, so dont process it */ | 3391 | /* Domain 0 is reserved, so dont process it */ |
| 3385 | if (!domain) | 3392 | if (!domain) |
| 3386 | return; | 3393 | return; |
| @@ -3388,14 +3395,12 @@ static void vm_domain_exit(struct dmar_domain *domain) | |||
| 3388 | vm_domain_remove_all_dev_info(domain); | 3395 | vm_domain_remove_all_dev_info(domain); |
| 3389 | /* destroy iovas */ | 3396 | /* destroy iovas */ |
| 3390 | put_iova_domain(&domain->iovad); | 3397 | put_iova_domain(&domain->iovad); |
| 3391 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
| 3392 | end = end & (~VTD_PAGE_MASK); | ||
| 3393 | 3398 | ||
| 3394 | /* clear ptes */ | 3399 | /* clear ptes */ |
| 3395 | dma_pte_clear_range(domain, 0, end); | 3400 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 3396 | 3401 | ||
| 3397 | /* free page tables */ | 3402 | /* free page tables */ |
| 3398 | dma_pte_free_pagetable(domain, 0, end); | 3403 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 3399 | 3404 | ||
| 3400 | iommu_free_vm_domain(domain); | 3405 | iommu_free_vm_domain(domain); |
| 3401 | free_domain_mem(domain); | 3406 | free_domain_mem(domain); |
| @@ -3504,7 +3509,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3504 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3509 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
| 3505 | prot |= DMA_PTE_SNP; | 3510 | prot |= DMA_PTE_SNP; |
| 3506 | 3511 | ||
| 3507 | max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size); | 3512 | max_addr = iova + size; |
| 3508 | if (dmar_domain->max_addr < max_addr) { | 3513 | if (dmar_domain->max_addr < max_addr) { |
| 3509 | int min_agaw; | 3514 | int min_agaw; |
| 3510 | u64 end; | 3515 | u64 end; |
| @@ -3522,8 +3527,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3522 | } | 3527 | } |
| 3523 | dmar_domain->max_addr = max_addr; | 3528 | dmar_domain->max_addr = max_addr; |
| 3524 | } | 3529 | } |
| 3525 | 3530 | /* Round up size to next multiple of PAGE_SIZE, if it and | |
| 3526 | ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot); | 3531 | the low bits of hpa would take us onto the next page */ |
| 3532 | size = aligned_nrpages(hpa, size); | ||
| 3533 | ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT, | ||
| 3534 | hpa >> VTD_PAGE_SHIFT, size, prot); | ||
| 3527 | return ret; | 3535 | return ret; |
| 3528 | } | 3536 | } |
| 3529 | 3537 | ||
| @@ -3531,15 +3539,12 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, | |||
| 3531 | unsigned long iova, size_t size) | 3539 | unsigned long iova, size_t size) |
| 3532 | { | 3540 | { |
| 3533 | struct dmar_domain *dmar_domain = domain->priv; | 3541 | struct dmar_domain *dmar_domain = domain->priv; |
| 3534 | dma_addr_t base; | ||
| 3535 | 3542 | ||
| 3536 | /* The address might not be aligned */ | 3543 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
| 3537 | base = iova & VTD_PAGE_MASK; | 3544 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
| 3538 | size = VTD_PAGE_ALIGN(size); | ||
| 3539 | dma_pte_clear_range(dmar_domain, base, base + size); | ||
| 3540 | 3545 | ||
| 3541 | if (dmar_domain->max_addr == base + size) | 3546 | if (dmar_domain->max_addr == iova + size) |
| 3542 | dmar_domain->max_addr = base; | 3547 | dmar_domain->max_addr = iova; |
| 3543 | } | 3548 | } |
| 3544 | 3549 | ||
| 3545 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3550 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
| @@ -3549,7 +3554,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | |||
| 3549 | struct dma_pte *pte; | 3554 | struct dma_pte *pte; |
| 3550 | u64 phys = 0; | 3555 | u64 phys = 0; |
| 3551 | 3556 | ||
| 3552 | pte = addr_to_dma_pte(dmar_domain, iova); | 3557 | pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT); |
| 3553 | if (pte) | 3558 | if (pte) |
| 3554 | phys = dma_pte_addr(pte); | 3559 | phys = dma_pte_addr(pte); |
| 3555 | 3560 | ||
