diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | arch/x86/Kconfig.debug | 8 | ||||
-rw-r--r-- | arch/x86/include/asm/amd_iommu_types.h | 47 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 453 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 129 |
5 files changed, 488 insertions, 154 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e87bdbfbcc75..5b776c6e7964 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -329,11 +329,6 @@ and is between 256 and 4096 characters. It is defined in the file | |||
329 | flushed before they will be reused, which | 329 | flushed before they will be reused, which |
330 | is a lot of faster | 330 | is a lot of faster |
331 | 331 | ||
332 | amd_iommu_size= [HW,X86-64] | ||
333 | Define the size of the aperture for the AMD IOMMU | ||
334 | driver. Possible values are: | ||
335 | '32M', '64M' (default), '128M', '256M', '512M', '1G' | ||
336 | |||
337 | amijoy.map= [HW,JOY] Amiga joystick support | 332 | amijoy.map= [HW,JOY] Amiga joystick support |
338 | Map of devices attached to JOY0DAT and JOY1DAT | 333 | Map of devices attached to JOY0DAT and JOY1DAT |
339 | Format: <a>,<b> | 334 | Format: <a>,<b> |
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 5865712d105d..33fac6bbe1c2 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug | |||
@@ -159,6 +159,14 @@ config IOMMU_DEBUG | |||
159 | options. See Documentation/x86_64/boot-options.txt for more | 159 | options. See Documentation/x86_64/boot-options.txt for more |
160 | details. | 160 | details. |
161 | 161 | ||
162 | config IOMMU_STRESS | ||
163 | bool "Enable IOMMU stress-test mode" | ||
164 | ---help--- | ||
165 | This option disables various optimizations in IOMMU related | ||
166 | code to do real stress testing of the IOMMU code. This option | ||
167 | will cause a performance drop and should only be enabled for | ||
168 | testing. | ||
169 | |||
162 | config IOMMU_LEAK | 170 | config IOMMU_LEAK |
163 | bool "IOMMU leak tracing" | 171 | bool "IOMMU leak tracing" |
164 | depends on IOMMU_DEBUG && DMA_API_DEBUG | 172 | depends on IOMMU_DEBUG && DMA_API_DEBUG |
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index cf5ef172cfca..0c878caaa0a2 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h | |||
@@ -194,6 +194,12 @@ | |||
194 | #define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */ | 194 | #define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */ |
195 | #define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops | 195 | #define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops |
196 | domain for an IOMMU */ | 196 | domain for an IOMMU */ |
197 | extern bool amd_iommu_dump; | ||
198 | #define DUMP_printk(format, arg...) \ | ||
199 | do { \ | ||
200 | if (amd_iommu_dump) \ | ||
201 | printk(KERN_INFO "AMD IOMMU: " format, ## arg); \ | ||
202 | } while(0); | ||
197 | 203 | ||
198 | /* | 204 | /* |
199 | * Make iterating over all IOMMUs easier | 205 | * Make iterating over all IOMMUs easier |
@@ -203,6 +209,13 @@ | |||
203 | #define for_each_iommu_safe(iommu, next) \ | 209 | #define for_each_iommu_safe(iommu, next) \ |
204 | list_for_each_entry_safe((iommu), (next), &amd_iommu_list, list) | 210 | list_for_each_entry_safe((iommu), (next), &amd_iommu_list, list) |
205 | 211 | ||
212 | #define APERTURE_RANGE_SHIFT 27 /* 128 MB */ | ||
213 | #define APERTURE_RANGE_SIZE (1ULL << APERTURE_RANGE_SHIFT) | ||
214 | #define APERTURE_RANGE_PAGES (APERTURE_RANGE_SIZE >> PAGE_SHIFT) | ||
215 | #define APERTURE_MAX_RANGES 32 /* allows 4GB of DMA address space */ | ||
216 | #define APERTURE_RANGE_INDEX(a) ((a) >> APERTURE_RANGE_SHIFT) | ||
217 | #define APERTURE_PAGE_INDEX(a) (((a) >> 21) & 0x3fULL) | ||
218 | |||
206 | /* | 219 | /* |
207 | * This structure contains generic data for IOMMU protection domains | 220 | * This structure contains generic data for IOMMU protection domains |
208 | * independent of their use. | 221 | * independent of their use. |
@@ -218,6 +231,26 @@ struct protection_domain { | |||
218 | }; | 231 | }; |
219 | 232 | ||
220 | /* | 233 | /* |
234 | * For dynamic growth the aperture size is split into ranges of 128MB of | ||
235 | * DMA address space each. This struct represents one such range. | ||
236 | */ | ||
237 | struct aperture_range { | ||
238 | |||
239 | /* address allocation bitmap */ | ||
240 | unsigned long *bitmap; | ||
241 | |||
242 | /* | ||
243 | * Array of PTE pages for the aperture. In this array we save all the | ||
244 | * leaf pages of the domain page table used for the aperture. This way | ||
245 | * we don't need to walk the page table to find a specific PTE. We can | ||
246 | * just calculate its address in constant time. | ||
247 | */ | ||
248 | u64 *pte_pages[64]; | ||
249 | |||
250 | unsigned long offset; | ||
251 | }; | ||
252 | |||
253 | /* | ||
221 | * Data container for a dma_ops specific protection domain | 254 | * Data container for a dma_ops specific protection domain |
222 | */ | 255 | */ |
223 | struct dma_ops_domain { | 256 | struct dma_ops_domain { |
@@ -230,18 +263,10 @@ struct dma_ops_domain { | |||
230 | unsigned long aperture_size; | 263 | unsigned long aperture_size; |
231 | 264 | ||
232 | /* address we start to search for free addresses */ | 265 | /* address we start to search for free addresses */ |
233 | unsigned long next_bit; | 266 | unsigned long next_address; |
234 | |||
235 | /* address allocation bitmap */ | ||
236 | unsigned long *bitmap; | ||
237 | 267 | ||
238 | /* | 268 | /* address space relevant data */ |
239 | * Array of PTE pages for the aperture. In this array we save all the | 269 | struct aperture_range *aperture[APERTURE_MAX_RANGES]; |
240 | * leaf pages of the domain page table used for the aperture. This way | ||
241 | * we don't need to walk the page table to find a specific PTE. We can | ||
242 | * just calculate its address in constant time. | ||
243 | */ | ||
244 | u64 **pte_pages; | ||
245 | 270 | ||
246 | /* This will be set to true when TLB needs to be flushed */ | 271 | /* This will be set to true when TLB needs to be flushed */ |
247 | bool need_flush; | 272 | bool need_flush; |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 92b0e1881e09..2c63d8748133 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -55,7 +55,16 @@ struct iommu_cmd { | |||
55 | static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, | 55 | static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, |
56 | struct unity_map_entry *e); | 56 | struct unity_map_entry *e); |
57 | static struct dma_ops_domain *find_protection_domain(u16 devid); | 57 | static struct dma_ops_domain *find_protection_domain(u16 devid); |
58 | static u64* alloc_pte(struct protection_domain *dom, | ||
59 | unsigned long address, u64 | ||
60 | **pte_page, gfp_t gfp); | ||
61 | static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, | ||
62 | unsigned long start_page, | ||
63 | unsigned int pages); | ||
58 | 64 | ||
65 | #ifndef BUS_NOTIFY_UNBOUND_DRIVER | ||
66 | #define BUS_NOTIFY_UNBOUND_DRIVER 0x0005 | ||
67 | #endif | ||
59 | 68 | ||
60 | #ifdef CONFIG_AMD_IOMMU_STATS | 69 | #ifdef CONFIG_AMD_IOMMU_STATS |
61 | 70 | ||
@@ -497,7 +506,7 @@ static int iommu_map_page(struct protection_domain *dom, | |||
497 | unsigned long phys_addr, | 506 | unsigned long phys_addr, |
498 | int prot) | 507 | int prot) |
499 | { | 508 | { |
500 | u64 __pte, *pte, *page; | 509 | u64 __pte, *pte; |
501 | 510 | ||
502 | bus_addr = PAGE_ALIGN(bus_addr); | 511 | bus_addr = PAGE_ALIGN(bus_addr); |
503 | phys_addr = PAGE_ALIGN(phys_addr); | 512 | phys_addr = PAGE_ALIGN(phys_addr); |
@@ -506,27 +515,7 @@ static int iommu_map_page(struct protection_domain *dom, | |||
506 | if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK)) | 515 | if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK)) |
507 | return -EINVAL; | 516 | return -EINVAL; |
508 | 517 | ||
509 | pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(bus_addr)]; | 518 | pte = alloc_pte(dom, bus_addr, NULL, GFP_KERNEL); |
510 | |||
511 | if (!IOMMU_PTE_PRESENT(*pte)) { | ||
512 | page = (u64 *)get_zeroed_page(GFP_KERNEL); | ||
513 | if (!page) | ||
514 | return -ENOMEM; | ||
515 | *pte = IOMMU_L2_PDE(virt_to_phys(page)); | ||
516 | } | ||
517 | |||
518 | pte = IOMMU_PTE_PAGE(*pte); | ||
519 | pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)]; | ||
520 | |||
521 | if (!IOMMU_PTE_PRESENT(*pte)) { | ||
522 | page = (u64 *)get_zeroed_page(GFP_KERNEL); | ||
523 | if (!page) | ||
524 | return -ENOMEM; | ||
525 | *pte = IOMMU_L1_PDE(virt_to_phys(page)); | ||
526 | } | ||
527 | |||
528 | pte = IOMMU_PTE_PAGE(*pte); | ||
529 | pte = &pte[IOMMU_PTE_L0_INDEX(bus_addr)]; | ||
530 | 519 | ||
531 | if (IOMMU_PTE_PRESENT(*pte)) | 520 | if (IOMMU_PTE_PRESENT(*pte)) |
532 | return -EBUSY; | 521 | return -EBUSY; |
@@ -624,7 +613,8 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, | |||
624 | * as allocated in the aperture | 613 | * as allocated in the aperture |
625 | */ | 614 | */ |
626 | if (addr < dma_dom->aperture_size) | 615 | if (addr < dma_dom->aperture_size) |
627 | __set_bit(addr >> PAGE_SHIFT, dma_dom->bitmap); | 616 | __set_bit(addr >> PAGE_SHIFT, |
617 | dma_dom->aperture[0]->bitmap); | ||
628 | } | 618 | } |
629 | 619 | ||
630 | return 0; | 620 | return 0; |
@@ -661,42 +651,191 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, | |||
661 | ****************************************************************************/ | 651 | ****************************************************************************/ |
662 | 652 | ||
663 | /* | 653 | /* |
664 | * The address allocator core function. | 654 | * The address allocator core functions. |
665 | * | 655 | * |
666 | * called with domain->lock held | 656 | * called with domain->lock held |
667 | */ | 657 | */ |
658 | |||
659 | /* | ||
660 | * This function checks if there is a PTE for a given dma address. If | ||
661 | * there is one, it returns the pointer to it. | ||
662 | */ | ||
663 | static u64* fetch_pte(struct protection_domain *domain, | ||
664 | unsigned long address) | ||
665 | { | ||
666 | u64 *pte; | ||
667 | |||
668 | pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(address)]; | ||
669 | |||
670 | if (!IOMMU_PTE_PRESENT(*pte)) | ||
671 | return NULL; | ||
672 | |||
673 | pte = IOMMU_PTE_PAGE(*pte); | ||
674 | pte = &pte[IOMMU_PTE_L1_INDEX(address)]; | ||
675 | |||
676 | if (!IOMMU_PTE_PRESENT(*pte)) | ||
677 | return NULL; | ||
678 | |||
679 | pte = IOMMU_PTE_PAGE(*pte); | ||
680 | pte = &pte[IOMMU_PTE_L0_INDEX(address)]; | ||
681 | |||
682 | return pte; | ||
683 | } | ||
684 | |||
685 | /* | ||
686 | * This function is used to add a new aperture range to an existing | ||
687 | * aperture in case of dma_ops domain allocation or address allocation | ||
688 | * failure. | ||
689 | */ | ||
690 | static int alloc_new_range(struct amd_iommu *iommu, | ||
691 | struct dma_ops_domain *dma_dom, | ||
692 | bool populate, gfp_t gfp) | ||
693 | { | ||
694 | int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; | ||
695 | int i; | ||
696 | |||
697 | #ifdef CONFIG_IOMMU_STRESS | ||
698 | populate = false; | ||
699 | #endif | ||
700 | |||
701 | if (index >= APERTURE_MAX_RANGES) | ||
702 | return -ENOMEM; | ||
703 | |||
704 | dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp); | ||
705 | if (!dma_dom->aperture[index]) | ||
706 | return -ENOMEM; | ||
707 | |||
708 | dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp); | ||
709 | if (!dma_dom->aperture[index]->bitmap) | ||
710 | goto out_free; | ||
711 | |||
712 | dma_dom->aperture[index]->offset = dma_dom->aperture_size; | ||
713 | |||
714 | if (populate) { | ||
715 | unsigned long address = dma_dom->aperture_size; | ||
716 | int i, num_ptes = APERTURE_RANGE_PAGES / 512; | ||
717 | u64 *pte, *pte_page; | ||
718 | |||
719 | for (i = 0; i < num_ptes; ++i) { | ||
720 | pte = alloc_pte(&dma_dom->domain, address, | ||
721 | &pte_page, gfp); | ||
722 | if (!pte) | ||
723 | goto out_free; | ||
724 | |||
725 | dma_dom->aperture[index]->pte_pages[i] = pte_page; | ||
726 | |||
727 | address += APERTURE_RANGE_SIZE / 64; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | dma_dom->aperture_size += APERTURE_RANGE_SIZE; | ||
732 | |||
733 | /* Intialize the exclusion range if necessary */ | ||
734 | if (iommu->exclusion_start && | ||
735 | iommu->exclusion_start >= dma_dom->aperture[index]->offset && | ||
736 | iommu->exclusion_start < dma_dom->aperture_size) { | ||
737 | unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT; | ||
738 | int pages = iommu_num_pages(iommu->exclusion_start, | ||
739 | iommu->exclusion_length, | ||
740 | PAGE_SIZE); | ||
741 | dma_ops_reserve_addresses(dma_dom, startpage, pages); | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Check for areas already mapped as present in the new aperture | ||
746 | * range and mark those pages as reserved in the allocator. Such | ||
747 | * mappings may already exist as a result of requested unity | ||
748 | * mappings for devices. | ||
749 | */ | ||
750 | for (i = dma_dom->aperture[index]->offset; | ||
751 | i < dma_dom->aperture_size; | ||
752 | i += PAGE_SIZE) { | ||
753 | u64 *pte = fetch_pte(&dma_dom->domain, i); | ||
754 | if (!pte || !IOMMU_PTE_PRESENT(*pte)) | ||
755 | continue; | ||
756 | |||
757 | dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1); | ||
758 | } | ||
759 | |||
760 | return 0; | ||
761 | |||
762 | out_free: | ||
763 | free_page((unsigned long)dma_dom->aperture[index]->bitmap); | ||
764 | |||
765 | kfree(dma_dom->aperture[index]); | ||
766 | dma_dom->aperture[index] = NULL; | ||
767 | |||
768 | return -ENOMEM; | ||
769 | } | ||
770 | |||
771 | static unsigned long dma_ops_area_alloc(struct device *dev, | ||
772 | struct dma_ops_domain *dom, | ||
773 | unsigned int pages, | ||
774 | unsigned long align_mask, | ||
775 | u64 dma_mask, | ||
776 | unsigned long start) | ||
777 | { | ||
778 | unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE; | ||
779 | int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT; | ||
780 | int i = start >> APERTURE_RANGE_SHIFT; | ||
781 | unsigned long boundary_size; | ||
782 | unsigned long address = -1; | ||
783 | unsigned long limit; | ||
784 | |||
785 | next_bit >>= PAGE_SHIFT; | ||
786 | |||
787 | boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, | ||
788 | PAGE_SIZE) >> PAGE_SHIFT; | ||
789 | |||
790 | for (;i < max_index; ++i) { | ||
791 | unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT; | ||
792 | |||
793 | if (dom->aperture[i]->offset >= dma_mask) | ||
794 | break; | ||
795 | |||
796 | limit = iommu_device_max_index(APERTURE_RANGE_PAGES, offset, | ||
797 | dma_mask >> PAGE_SHIFT); | ||
798 | |||
799 | address = iommu_area_alloc(dom->aperture[i]->bitmap, | ||
800 | limit, next_bit, pages, 0, | ||
801 | boundary_size, align_mask); | ||
802 | if (address != -1) { | ||
803 | address = dom->aperture[i]->offset + | ||
804 | (address << PAGE_SHIFT); | ||
805 | dom->next_address = address + (pages << PAGE_SHIFT); | ||
806 | break; | ||
807 | } | ||
808 | |||
809 | next_bit = 0; | ||
810 | } | ||
811 | |||
812 | return address; | ||
813 | } | ||
814 | |||
668 | static unsigned long dma_ops_alloc_addresses(struct device *dev, | 815 | static unsigned long dma_ops_alloc_addresses(struct device *dev, |
669 | struct dma_ops_domain *dom, | 816 | struct dma_ops_domain *dom, |
670 | unsigned int pages, | 817 | unsigned int pages, |
671 | unsigned long align_mask, | 818 | unsigned long align_mask, |
672 | u64 dma_mask) | 819 | u64 dma_mask) |
673 | { | 820 | { |
674 | unsigned long limit; | ||
675 | unsigned long address; | 821 | unsigned long address; |
676 | unsigned long boundary_size; | ||
677 | 822 | ||
678 | boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, | 823 | #ifdef CONFIG_IOMMU_STRESS |
679 | PAGE_SIZE) >> PAGE_SHIFT; | 824 | dom->next_address = 0; |
680 | limit = iommu_device_max_index(dom->aperture_size >> PAGE_SHIFT, 0, | 825 | dom->need_flush = true; |
681 | dma_mask >> PAGE_SHIFT); | 826 | #endif |
682 | 827 | ||
683 | if (dom->next_bit >= limit) { | 828 | address = dma_ops_area_alloc(dev, dom, pages, align_mask, |
684 | dom->next_bit = 0; | 829 | dma_mask, dom->next_address); |
685 | dom->need_flush = true; | ||
686 | } | ||
687 | 830 | ||
688 | address = iommu_area_alloc(dom->bitmap, limit, dom->next_bit, pages, | ||
689 | 0 , boundary_size, align_mask); | ||
690 | if (address == -1) { | 831 | if (address == -1) { |
691 | address = iommu_area_alloc(dom->bitmap, limit, 0, pages, | 832 | dom->next_address = 0; |
692 | 0, boundary_size, align_mask); | 833 | address = dma_ops_area_alloc(dev, dom, pages, align_mask, |
834 | dma_mask, 0); | ||
693 | dom->need_flush = true; | 835 | dom->need_flush = true; |
694 | } | 836 | } |
695 | 837 | ||
696 | if (likely(address != -1)) { | 838 | if (unlikely(address == -1)) |
697 | dom->next_bit = address + pages; | ||
698 | address <<= PAGE_SHIFT; | ||
699 | } else | ||
700 | address = bad_dma_address; | 839 | address = bad_dma_address; |
701 | 840 | ||
702 | WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size); | 841 | WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size); |
@@ -713,11 +852,23 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom, | |||
713 | unsigned long address, | 852 | unsigned long address, |
714 | unsigned int pages) | 853 | unsigned int pages) |
715 | { | 854 | { |
716 | address >>= PAGE_SHIFT; | 855 | unsigned i = address >> APERTURE_RANGE_SHIFT; |
717 | iommu_area_free(dom->bitmap, address, pages); | 856 | struct aperture_range *range = dom->aperture[i]; |
857 | |||
858 | BUG_ON(i >= APERTURE_MAX_RANGES || range == NULL); | ||
859 | |||
860 | #ifdef CONFIG_IOMMU_STRESS | ||
861 | if (i < 4) | ||
862 | return; | ||
863 | #endif | ||
718 | 864 | ||
719 | if (address >= dom->next_bit) | 865 | if (address >= dom->next_address) |
720 | dom->need_flush = true; | 866 | dom->need_flush = true; |
867 | |||
868 | address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT; | ||
869 | |||
870 | iommu_area_free(range->bitmap, address, pages); | ||
871 | |||
721 | } | 872 | } |
722 | 873 | ||
723 | /**************************************************************************** | 874 | /**************************************************************************** |
@@ -765,12 +916,16 @@ static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, | |||
765 | unsigned long start_page, | 916 | unsigned long start_page, |
766 | unsigned int pages) | 917 | unsigned int pages) |
767 | { | 918 | { |
768 | unsigned int last_page = dom->aperture_size >> PAGE_SHIFT; | 919 | unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT; |
769 | 920 | ||
770 | if (start_page + pages > last_page) | 921 | if (start_page + pages > last_page) |
771 | pages = last_page - start_page; | 922 | pages = last_page - start_page; |
772 | 923 | ||
773 | iommu_area_reserve(dom->bitmap, start_page, pages); | 924 | for (i = start_page; i < start_page + pages; ++i) { |
925 | int index = i / APERTURE_RANGE_PAGES; | ||
926 | int page = i % APERTURE_RANGE_PAGES; | ||
927 | __set_bit(page, dom->aperture[index]->bitmap); | ||
928 | } | ||
774 | } | 929 | } |
775 | 930 | ||
776 | static void free_pagetable(struct protection_domain *domain) | 931 | static void free_pagetable(struct protection_domain *domain) |
@@ -809,14 +964,19 @@ static void free_pagetable(struct protection_domain *domain) | |||
809 | */ | 964 | */ |
810 | static void dma_ops_domain_free(struct dma_ops_domain *dom) | 965 | static void dma_ops_domain_free(struct dma_ops_domain *dom) |
811 | { | 966 | { |
967 | int i; | ||
968 | |||
812 | if (!dom) | 969 | if (!dom) |
813 | return; | 970 | return; |
814 | 971 | ||
815 | free_pagetable(&dom->domain); | 972 | free_pagetable(&dom->domain); |
816 | 973 | ||
817 | kfree(dom->pte_pages); | 974 | for (i = 0; i < APERTURE_MAX_RANGES; ++i) { |
818 | 975 | if (!dom->aperture[i]) | |
819 | kfree(dom->bitmap); | 976 | continue; |
977 | free_page((unsigned long)dom->aperture[i]->bitmap); | ||
978 | kfree(dom->aperture[i]); | ||
979 | } | ||
820 | 980 | ||
821 | kfree(dom); | 981 | kfree(dom); |
822 | } | 982 | } |
@@ -826,19 +986,9 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom) | |||
826 | * It also intializes the page table and the address allocator data | 986 | * It also intializes the page table and the address allocator data |
827 | * structures required for the dma_ops interface | 987 | * structures required for the dma_ops interface |
828 | */ | 988 | */ |
829 | static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, | 989 | static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu) |
830 | unsigned order) | ||
831 | { | 990 | { |
832 | struct dma_ops_domain *dma_dom; | 991 | struct dma_ops_domain *dma_dom; |
833 | unsigned i, num_pte_pages; | ||
834 | u64 *l2_pde; | ||
835 | u64 address; | ||
836 | |||
837 | /* | ||
838 | * Currently the DMA aperture must be between 32 MB and 1GB in size | ||
839 | */ | ||
840 | if ((order < 25) || (order > 30)) | ||
841 | return NULL; | ||
842 | 992 | ||
843 | dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL); | 993 | dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL); |
844 | if (!dma_dom) | 994 | if (!dma_dom) |
@@ -855,55 +1005,20 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu, | |||
855 | dma_dom->domain.priv = dma_dom; | 1005 | dma_dom->domain.priv = dma_dom; |
856 | if (!dma_dom->domain.pt_root) | 1006 | if (!dma_dom->domain.pt_root) |
857 | goto free_dma_dom; | 1007 | goto free_dma_dom; |
858 | dma_dom->aperture_size = (1ULL << order); | ||
859 | dma_dom->bitmap = kzalloc(dma_dom->aperture_size / (PAGE_SIZE * 8), | ||
860 | GFP_KERNEL); | ||
861 | if (!dma_dom->bitmap) | ||
862 | goto free_dma_dom; | ||
863 | /* | ||
864 | * mark the first page as allocated so we never return 0 as | ||
865 | * a valid dma-address. So we can use 0 as error value | ||
866 | */ | ||
867 | dma_dom->bitmap[0] = 1; | ||
868 | dma_dom->next_bit = 0; | ||
869 | 1008 | ||
870 | dma_dom->need_flush = false; | 1009 | dma_dom->need_flush = false; |
871 | dma_dom->target_dev = 0xffff; | 1010 | dma_dom->target_dev = 0xffff; |
872 | 1011 | ||
873 | /* Intialize the exclusion range if necessary */ | 1012 | if (alloc_new_range(iommu, dma_dom, true, GFP_KERNEL)) |
874 | if (iommu->exclusion_start && | 1013 | goto free_dma_dom; |
875 | iommu->exclusion_start < dma_dom->aperture_size) { | ||
876 | unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT; | ||
877 | int pages = iommu_num_pages(iommu->exclusion_start, | ||
878 | iommu->exclusion_length, | ||
879 | PAGE_SIZE); | ||
880 | dma_ops_reserve_addresses(dma_dom, startpage, pages); | ||
881 | } | ||
882 | 1014 | ||
883 | /* | 1015 | /* |
884 | * At the last step, build the page tables so we don't need to | 1016 | * mark the first page as allocated so we never return 0 as |
885 | * allocate page table pages in the dma_ops mapping/unmapping | 1017 | * a valid dma-address. So we can use 0 as error value |
886 | * path. | ||
887 | */ | 1018 | */ |
888 | num_pte_pages = dma_dom->aperture_size / (PAGE_SIZE * 512); | 1019 | dma_dom->aperture[0]->bitmap[0] = 1; |
889 | dma_dom->pte_pages = kzalloc(num_pte_pages * sizeof(void *), | 1020 | dma_dom->next_address = 0; |
890 | GFP_KERNEL); | ||
891 | if (!dma_dom->pte_pages) | ||
892 | goto free_dma_dom; | ||
893 | 1021 | ||
894 | l2_pde = (u64 *)get_zeroed_page(GFP_KERNEL); | ||
895 | if (l2_pde == NULL) | ||
896 | goto free_dma_dom; | ||
897 | |||
898 | dma_dom->domain.pt_root[0] = IOMMU_L2_PDE(virt_to_phys(l2_pde)); | ||
899 | |||
900 | for (i = 0; i < num_pte_pages; ++i) { | ||
901 | dma_dom->pte_pages[i] = (u64 *)get_zeroed_page(GFP_KERNEL); | ||
902 | if (!dma_dom->pte_pages[i]) | ||
903 | goto free_dma_dom; | ||
904 | address = virt_to_phys(dma_dom->pte_pages[i]); | ||
905 | l2_pde[i] = IOMMU_L1_PDE(address); | ||
906 | } | ||
907 | 1022 | ||
908 | return dma_dom; | 1023 | return dma_dom; |
909 | 1024 | ||
@@ -1012,7 +1127,6 @@ static int device_change_notifier(struct notifier_block *nb, | |||
1012 | struct protection_domain *domain; | 1127 | struct protection_domain *domain; |
1013 | struct dma_ops_domain *dma_domain; | 1128 | struct dma_ops_domain *dma_domain; |
1014 | struct amd_iommu *iommu; | 1129 | struct amd_iommu *iommu; |
1015 | int order = amd_iommu_aperture_order; | ||
1016 | unsigned long flags; | 1130 | unsigned long flags; |
1017 | 1131 | ||
1018 | if (devid > amd_iommu_last_bdf) | 1132 | if (devid > amd_iommu_last_bdf) |
@@ -1038,10 +1152,11 @@ static int device_change_notifier(struct notifier_block *nb, | |||
1038 | if (!dma_domain) | 1152 | if (!dma_domain) |
1039 | dma_domain = iommu->default_dom; | 1153 | dma_domain = iommu->default_dom; |
1040 | attach_device(iommu, &dma_domain->domain, devid); | 1154 | attach_device(iommu, &dma_domain->domain, devid); |
1041 | printk(KERN_INFO "AMD IOMMU: Using protection domain %d for " | 1155 | DUMP_printk(KERN_INFO "AMD IOMMU: Using protection domain " |
1042 | "device %s\n", dma_domain->domain.id, dev_name(dev)); | 1156 | "%d for device %s\n", |
1157 | dma_domain->domain.id, dev_name(dev)); | ||
1043 | break; | 1158 | break; |
1044 | case BUS_NOTIFY_UNBIND_DRIVER: | 1159 | case BUS_NOTIFY_UNBOUND_DRIVER: |
1045 | if (!domain) | 1160 | if (!domain) |
1046 | goto out; | 1161 | goto out; |
1047 | detach_device(domain, devid); | 1162 | detach_device(domain, devid); |
@@ -1051,7 +1166,7 @@ static int device_change_notifier(struct notifier_block *nb, | |||
1051 | dma_domain = find_protection_domain(devid); | 1166 | dma_domain = find_protection_domain(devid); |
1052 | if (dma_domain) | 1167 | if (dma_domain) |
1053 | goto out; | 1168 | goto out; |
1054 | dma_domain = dma_ops_domain_alloc(iommu, order); | 1169 | dma_domain = dma_ops_domain_alloc(iommu); |
1055 | if (!dma_domain) | 1170 | if (!dma_domain) |
1056 | goto out; | 1171 | goto out; |
1057 | dma_domain->target_dev = devid; | 1172 | dma_domain->target_dev = devid; |
@@ -1162,8 +1277,9 @@ static int get_device_resources(struct device *dev, | |||
1162 | dma_dom = (*iommu)->default_dom; | 1277 | dma_dom = (*iommu)->default_dom; |
1163 | *domain = &dma_dom->domain; | 1278 | *domain = &dma_dom->domain; |
1164 | attach_device(*iommu, *domain, *bdf); | 1279 | attach_device(*iommu, *domain, *bdf); |
1165 | printk(KERN_INFO "AMD IOMMU: Using protection domain %d for " | 1280 | DUMP_printk(KERN_INFO "AMD IOMMU: Using protection domain " |
1166 | "device %s\n", (*domain)->id, dev_name(dev)); | 1281 | "%d for device %s\n", |
1282 | (*domain)->id, dev_name(dev)); | ||
1167 | } | 1283 | } |
1168 | 1284 | ||
1169 | if (domain_for_device(_bdf) == NULL) | 1285 | if (domain_for_device(_bdf) == NULL) |
@@ -1173,6 +1289,66 @@ static int get_device_resources(struct device *dev, | |||
1173 | } | 1289 | } |
1174 | 1290 | ||
1175 | /* | 1291 | /* |
1292 | * If the pte_page is not yet allocated this function is called | ||
1293 | */ | ||
1294 | static u64* alloc_pte(struct protection_domain *dom, | ||
1295 | unsigned long address, u64 **pte_page, gfp_t gfp) | ||
1296 | { | ||
1297 | u64 *pte, *page; | ||
1298 | |||
1299 | pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(address)]; | ||
1300 | |||
1301 | if (!IOMMU_PTE_PRESENT(*pte)) { | ||
1302 | page = (u64 *)get_zeroed_page(gfp); | ||
1303 | if (!page) | ||
1304 | return NULL; | ||
1305 | *pte = IOMMU_L2_PDE(virt_to_phys(page)); | ||
1306 | } | ||
1307 | |||
1308 | pte = IOMMU_PTE_PAGE(*pte); | ||
1309 | pte = &pte[IOMMU_PTE_L1_INDEX(address)]; | ||
1310 | |||
1311 | if (!IOMMU_PTE_PRESENT(*pte)) { | ||
1312 | page = (u64 *)get_zeroed_page(gfp); | ||
1313 | if (!page) | ||
1314 | return NULL; | ||
1315 | *pte = IOMMU_L1_PDE(virt_to_phys(page)); | ||
1316 | } | ||
1317 | |||
1318 | pte = IOMMU_PTE_PAGE(*pte); | ||
1319 | |||
1320 | if (pte_page) | ||
1321 | *pte_page = pte; | ||
1322 | |||
1323 | pte = &pte[IOMMU_PTE_L0_INDEX(address)]; | ||
1324 | |||
1325 | return pte; | ||
1326 | } | ||
1327 | |||
1328 | /* | ||
1329 | * This function fetches the PTE for a given address in the aperture | ||
1330 | */ | ||
1331 | static u64* dma_ops_get_pte(struct dma_ops_domain *dom, | ||
1332 | unsigned long address) | ||
1333 | { | ||
1334 | struct aperture_range *aperture; | ||
1335 | u64 *pte, *pte_page; | ||
1336 | |||
1337 | aperture = dom->aperture[APERTURE_RANGE_INDEX(address)]; | ||
1338 | if (!aperture) | ||
1339 | return NULL; | ||
1340 | |||
1341 | pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; | ||
1342 | if (!pte) { | ||
1343 | pte = alloc_pte(&dom->domain, address, &pte_page, GFP_ATOMIC); | ||
1344 | aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page; | ||
1345 | } else | ||
1346 | pte += IOMMU_PTE_L0_INDEX(address); | ||
1347 | |||
1348 | return pte; | ||
1349 | } | ||
1350 | |||
1351 | /* | ||
1176 | * This is the generic map function. It maps one 4kb page at paddr to | 1352 | * This is the generic map function. It maps one 4kb page at paddr to |
1177 | * the given address in the DMA address space for the domain. | 1353 | * the given address in the DMA address space for the domain. |
1178 | */ | 1354 | */ |
@@ -1188,8 +1364,9 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu, | |||
1188 | 1364 | ||
1189 | paddr &= PAGE_MASK; | 1365 | paddr &= PAGE_MASK; |
1190 | 1366 | ||
1191 | pte = dom->pte_pages[IOMMU_PTE_L1_INDEX(address)]; | 1367 | pte = dma_ops_get_pte(dom, address); |
1192 | pte += IOMMU_PTE_L0_INDEX(address); | 1368 | if (!pte) |
1369 | return bad_dma_address; | ||
1193 | 1370 | ||
1194 | __pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC; | 1371 | __pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC; |
1195 | 1372 | ||
@@ -1214,14 +1391,20 @@ static void dma_ops_domain_unmap(struct amd_iommu *iommu, | |||
1214 | struct dma_ops_domain *dom, | 1391 | struct dma_ops_domain *dom, |
1215 | unsigned long address) | 1392 | unsigned long address) |
1216 | { | 1393 | { |
1394 | struct aperture_range *aperture; | ||
1217 | u64 *pte; | 1395 | u64 *pte; |
1218 | 1396 | ||
1219 | if (address >= dom->aperture_size) | 1397 | if (address >= dom->aperture_size) |
1220 | return; | 1398 | return; |
1221 | 1399 | ||
1222 | WARN_ON(address & ~PAGE_MASK || address >= dom->aperture_size); | 1400 | aperture = dom->aperture[APERTURE_RANGE_INDEX(address)]; |
1401 | if (!aperture) | ||
1402 | return; | ||
1403 | |||
1404 | pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; | ||
1405 | if (!pte) | ||
1406 | return; | ||
1223 | 1407 | ||
1224 | pte = dom->pte_pages[IOMMU_PTE_L1_INDEX(address)]; | ||
1225 | pte += IOMMU_PTE_L0_INDEX(address); | 1408 | pte += IOMMU_PTE_L0_INDEX(address); |
1226 | 1409 | ||
1227 | WARN_ON(!*pte); | 1410 | WARN_ON(!*pte); |
@@ -1245,7 +1428,7 @@ static dma_addr_t __map_single(struct device *dev, | |||
1245 | u64 dma_mask) | 1428 | u64 dma_mask) |
1246 | { | 1429 | { |
1247 | dma_addr_t offset = paddr & ~PAGE_MASK; | 1430 | dma_addr_t offset = paddr & ~PAGE_MASK; |
1248 | dma_addr_t address, start; | 1431 | dma_addr_t address, start, ret; |
1249 | unsigned int pages; | 1432 | unsigned int pages; |
1250 | unsigned long align_mask = 0; | 1433 | unsigned long align_mask = 0; |
1251 | int i; | 1434 | int i; |
@@ -1261,14 +1444,33 @@ static dma_addr_t __map_single(struct device *dev, | |||
1261 | if (align) | 1444 | if (align) |
1262 | align_mask = (1UL << get_order(size)) - 1; | 1445 | align_mask = (1UL << get_order(size)) - 1; |
1263 | 1446 | ||
1447 | retry: | ||
1264 | address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, | 1448 | address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, |
1265 | dma_mask); | 1449 | dma_mask); |
1266 | if (unlikely(address == bad_dma_address)) | 1450 | if (unlikely(address == bad_dma_address)) { |
1267 | goto out; | 1451 | /* |
1452 | * setting next_address here will let the address | ||
1453 | * allocator only scan the new allocated range in the | ||
1454 | * first run. This is a small optimization. | ||
1455 | */ | ||
1456 | dma_dom->next_address = dma_dom->aperture_size; | ||
1457 | |||
1458 | if (alloc_new_range(iommu, dma_dom, false, GFP_ATOMIC)) | ||
1459 | goto out; | ||
1460 | |||
1461 | /* | ||
1462 | * aperture was sucessfully enlarged by 128 MB, try | ||
1463 | * allocation again | ||
1464 | */ | ||
1465 | goto retry; | ||
1466 | } | ||
1268 | 1467 | ||
1269 | start = address; | 1468 | start = address; |
1270 | for (i = 0; i < pages; ++i) { | 1469 | for (i = 0; i < pages; ++i) { |
1271 | dma_ops_domain_map(iommu, dma_dom, start, paddr, dir); | 1470 | ret = dma_ops_domain_map(iommu, dma_dom, start, paddr, dir); |
1471 | if (ret == bad_dma_address) | ||
1472 | goto out_unmap; | ||
1473 | |||
1272 | paddr += PAGE_SIZE; | 1474 | paddr += PAGE_SIZE; |
1273 | start += PAGE_SIZE; | 1475 | start += PAGE_SIZE; |
1274 | } | 1476 | } |
@@ -1284,6 +1486,17 @@ static dma_addr_t __map_single(struct device *dev, | |||
1284 | 1486 | ||
1285 | out: | 1487 | out: |
1286 | return address; | 1488 | return address; |
1489 | |||
1490 | out_unmap: | ||
1491 | |||
1492 | for (--i; i >= 0; --i) { | ||
1493 | start -= PAGE_SIZE; | ||
1494 | dma_ops_domain_unmap(iommu, dma_dom, start); | ||
1495 | } | ||
1496 | |||
1497 | dma_ops_free_addresses(dma_dom, address, pages); | ||
1498 | |||
1499 | return bad_dma_address; | ||
1287 | } | 1500 | } |
1288 | 1501 | ||
1289 | /* | 1502 | /* |
@@ -1654,7 +1867,6 @@ static void prealloc_protection_domains(void) | |||
1654 | struct pci_dev *dev = NULL; | 1867 | struct pci_dev *dev = NULL; |
1655 | struct dma_ops_domain *dma_dom; | 1868 | struct dma_ops_domain *dma_dom; |
1656 | struct amd_iommu *iommu; | 1869 | struct amd_iommu *iommu; |
1657 | int order = amd_iommu_aperture_order; | ||
1658 | u16 devid; | 1870 | u16 devid; |
1659 | 1871 | ||
1660 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 1872 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
@@ -1667,7 +1879,7 @@ static void prealloc_protection_domains(void) | |||
1667 | iommu = amd_iommu_rlookup_table[devid]; | 1879 | iommu = amd_iommu_rlookup_table[devid]; |
1668 | if (!iommu) | 1880 | if (!iommu) |
1669 | continue; | 1881 | continue; |
1670 | dma_dom = dma_ops_domain_alloc(iommu, order); | 1882 | dma_dom = dma_ops_domain_alloc(iommu); |
1671 | if (!dma_dom) | 1883 | if (!dma_dom) |
1672 | continue; | 1884 | continue; |
1673 | init_unity_mappings_for_device(dma_dom, devid); | 1885 | init_unity_mappings_for_device(dma_dom, devid); |
@@ -1693,7 +1905,6 @@ static struct dma_map_ops amd_iommu_dma_ops = { | |||
1693 | int __init amd_iommu_init_dma_ops(void) | 1905 | int __init amd_iommu_init_dma_ops(void) |
1694 | { | 1906 | { |
1695 | struct amd_iommu *iommu; | 1907 | struct amd_iommu *iommu; |
1696 | int order = amd_iommu_aperture_order; | ||
1697 | int ret; | 1908 | int ret; |
1698 | 1909 | ||
1699 | /* | 1910 | /* |
@@ -1702,7 +1913,7 @@ int __init amd_iommu_init_dma_ops(void) | |||
1702 | * protection domain will be assigned to the default one. | 1913 | * protection domain will be assigned to the default one. |
1703 | */ | 1914 | */ |
1704 | for_each_iommu(iommu) { | 1915 | for_each_iommu(iommu) { |
1705 | iommu->default_dom = dma_ops_domain_alloc(iommu, order); | 1916 | iommu->default_dom = dma_ops_domain_alloc(iommu); |
1706 | if (iommu->default_dom == NULL) | 1917 | if (iommu->default_dom == NULL) |
1707 | return -ENOMEM; | 1918 | return -ENOMEM; |
1708 | iommu->default_dom->domain.flags |= PD_DEFAULT_MASK; | 1919 | iommu->default_dom->domain.flags |= PD_DEFAULT_MASK; |
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 4ca8fbfb68dc..238989ec077d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -115,15 +115,21 @@ struct ivmd_header { | |||
115 | u64 range_length; | 115 | u64 range_length; |
116 | } __attribute__((packed)); | 116 | } __attribute__((packed)); |
117 | 117 | ||
118 | bool amd_iommu_dump; | ||
119 | |||
118 | static int __initdata amd_iommu_detected; | 120 | static int __initdata amd_iommu_detected; |
119 | 121 | ||
120 | u16 amd_iommu_last_bdf; /* largest PCI device id we have | 122 | u16 amd_iommu_last_bdf; /* largest PCI device id we have |
121 | to handle */ | 123 | to handle */ |
122 | LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings | 124 | LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings |
123 | we find in ACPI */ | 125 | we find in ACPI */ |
124 | unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */ | 126 | #ifdef CONFIG_IOMMU_STRESS |
127 | bool amd_iommu_isolate = false; | ||
128 | #else | ||
125 | bool amd_iommu_isolate = true; /* if true, device isolation is | 129 | bool amd_iommu_isolate = true; /* if true, device isolation is |
126 | enabled */ | 130 | enabled */ |
131 | #endif | ||
132 | |||
127 | bool amd_iommu_unmap_flush; /* if true, flush on every unmap */ | 133 | bool amd_iommu_unmap_flush; /* if true, flush on every unmap */ |
128 | 134 | ||
129 | LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the | 135 | LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the |
@@ -175,7 +181,7 @@ static inline void update_last_devid(u16 devid) | |||
175 | static inline unsigned long tbl_size(int entry_size) | 181 | static inline unsigned long tbl_size(int entry_size) |
176 | { | 182 | { |
177 | unsigned shift = PAGE_SHIFT + | 183 | unsigned shift = PAGE_SHIFT + |
178 | get_order(amd_iommu_last_bdf * entry_size); | 184 | get_order(((int)amd_iommu_last_bdf + 1) * entry_size); |
179 | 185 | ||
180 | return 1UL << shift; | 186 | return 1UL << shift; |
181 | } | 187 | } |
@@ -612,32 +618,83 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
612 | p += sizeof(struct ivhd_header); | 618 | p += sizeof(struct ivhd_header); |
613 | end += h->length; | 619 | end += h->length; |
614 | 620 | ||
621 | |||
615 | while (p < end) { | 622 | while (p < end) { |
616 | e = (struct ivhd_entry *)p; | 623 | e = (struct ivhd_entry *)p; |
617 | switch (e->type) { | 624 | switch (e->type) { |
618 | case IVHD_DEV_ALL: | 625 | case IVHD_DEV_ALL: |
626 | |||
627 | DUMP_printk(" DEV_ALL\t\t\t first devid: %02x:%02x.%x" | ||
628 | " last device %02x:%02x.%x flags: %02x\n", | ||
629 | PCI_BUS(iommu->first_device), | ||
630 | PCI_SLOT(iommu->first_device), | ||
631 | PCI_FUNC(iommu->first_device), | ||
632 | PCI_BUS(iommu->last_device), | ||
633 | PCI_SLOT(iommu->last_device), | ||
634 | PCI_FUNC(iommu->last_device), | ||
635 | e->flags); | ||
636 | |||
619 | for (dev_i = iommu->first_device; | 637 | for (dev_i = iommu->first_device; |
620 | dev_i <= iommu->last_device; ++dev_i) | 638 | dev_i <= iommu->last_device; ++dev_i) |
621 | set_dev_entry_from_acpi(iommu, dev_i, | 639 | set_dev_entry_from_acpi(iommu, dev_i, |
622 | e->flags, 0); | 640 | e->flags, 0); |
623 | break; | 641 | break; |
624 | case IVHD_DEV_SELECT: | 642 | case IVHD_DEV_SELECT: |
643 | |||
644 | DUMP_printk(" DEV_SELECT\t\t\t devid: %02x:%02x.%x " | ||
645 | "flags: %02x\n", | ||
646 | PCI_BUS(e->devid), | ||
647 | PCI_SLOT(e->devid), | ||
648 | PCI_FUNC(e->devid), | ||
649 | e->flags); | ||
650 | |||
625 | devid = e->devid; | 651 | devid = e->devid; |
626 | set_dev_entry_from_acpi(iommu, devid, e->flags, 0); | 652 | set_dev_entry_from_acpi(iommu, devid, e->flags, 0); |
627 | break; | 653 | break; |
628 | case IVHD_DEV_SELECT_RANGE_START: | 654 | case IVHD_DEV_SELECT_RANGE_START: |
655 | |||
656 | DUMP_printk(" DEV_SELECT_RANGE_START\t " | ||
657 | "devid: %02x:%02x.%x flags: %02x\n", | ||
658 | PCI_BUS(e->devid), | ||
659 | PCI_SLOT(e->devid), | ||
660 | PCI_FUNC(e->devid), | ||
661 | e->flags); | ||
662 | |||
629 | devid_start = e->devid; | 663 | devid_start = e->devid; |
630 | flags = e->flags; | 664 | flags = e->flags; |
631 | ext_flags = 0; | 665 | ext_flags = 0; |
632 | alias = false; | 666 | alias = false; |
633 | break; | 667 | break; |
634 | case IVHD_DEV_ALIAS: | 668 | case IVHD_DEV_ALIAS: |
669 | |||
670 | DUMP_printk(" DEV_ALIAS\t\t\t devid: %02x:%02x.%x " | ||
671 | "flags: %02x devid_to: %02x:%02x.%x\n", | ||
672 | PCI_BUS(e->devid), | ||
673 | PCI_SLOT(e->devid), | ||
674 | PCI_FUNC(e->devid), | ||
675 | e->flags, | ||
676 | PCI_BUS(e->ext >> 8), | ||
677 | PCI_SLOT(e->ext >> 8), | ||
678 | PCI_FUNC(e->ext >> 8)); | ||
679 | |||
635 | devid = e->devid; | 680 | devid = e->devid; |
636 | devid_to = e->ext >> 8; | 681 | devid_to = e->ext >> 8; |
637 | set_dev_entry_from_acpi(iommu, devid, e->flags, 0); | 682 | set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); |
638 | amd_iommu_alias_table[devid] = devid_to; | 683 | amd_iommu_alias_table[devid] = devid_to; |
639 | break; | 684 | break; |
640 | case IVHD_DEV_ALIAS_RANGE: | 685 | case IVHD_DEV_ALIAS_RANGE: |
686 | |||
687 | DUMP_printk(" DEV_ALIAS_RANGE\t\t " | ||
688 | "devid: %02x:%02x.%x flags: %02x " | ||
689 | "devid_to: %02x:%02x.%x\n", | ||
690 | PCI_BUS(e->devid), | ||
691 | PCI_SLOT(e->devid), | ||
692 | PCI_FUNC(e->devid), | ||
693 | e->flags, | ||
694 | PCI_BUS(e->ext >> 8), | ||
695 | PCI_SLOT(e->ext >> 8), | ||
696 | PCI_FUNC(e->ext >> 8)); | ||
697 | |||
641 | devid_start = e->devid; | 698 | devid_start = e->devid; |
642 | flags = e->flags; | 699 | flags = e->flags; |
643 | devid_to = e->ext >> 8; | 700 | devid_to = e->ext >> 8; |
@@ -645,17 +702,39 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
645 | alias = true; | 702 | alias = true; |
646 | break; | 703 | break; |
647 | case IVHD_DEV_EXT_SELECT: | 704 | case IVHD_DEV_EXT_SELECT: |
705 | |||
706 | DUMP_printk(" DEV_EXT_SELECT\t\t devid: %02x:%02x.%x " | ||
707 | "flags: %02x ext: %08x\n", | ||
708 | PCI_BUS(e->devid), | ||
709 | PCI_SLOT(e->devid), | ||
710 | PCI_FUNC(e->devid), | ||
711 | e->flags, e->ext); | ||
712 | |||
648 | devid = e->devid; | 713 | devid = e->devid; |
649 | set_dev_entry_from_acpi(iommu, devid, e->flags, | 714 | set_dev_entry_from_acpi(iommu, devid, e->flags, |
650 | e->ext); | 715 | e->ext); |
651 | break; | 716 | break; |
652 | case IVHD_DEV_EXT_SELECT_RANGE: | 717 | case IVHD_DEV_EXT_SELECT_RANGE: |
718 | |||
719 | DUMP_printk(" DEV_EXT_SELECT_RANGE\t devid: " | ||
720 | "%02x:%02x.%x flags: %02x ext: %08x\n", | ||
721 | PCI_BUS(e->devid), | ||
722 | PCI_SLOT(e->devid), | ||
723 | PCI_FUNC(e->devid), | ||
724 | e->flags, e->ext); | ||
725 | |||
653 | devid_start = e->devid; | 726 | devid_start = e->devid; |
654 | flags = e->flags; | 727 | flags = e->flags; |
655 | ext_flags = e->ext; | 728 | ext_flags = e->ext; |
656 | alias = false; | 729 | alias = false; |
657 | break; | 730 | break; |
658 | case IVHD_DEV_RANGE_END: | 731 | case IVHD_DEV_RANGE_END: |
732 | |||
733 | DUMP_printk(" DEV_RANGE_END\t\t devid: %02x:%02x.%x\n", | ||
734 | PCI_BUS(e->devid), | ||
735 | PCI_SLOT(e->devid), | ||
736 | PCI_FUNC(e->devid)); | ||
737 | |||
659 | devid = e->devid; | 738 | devid = e->devid; |
660 | for (dev_i = devid_start; dev_i <= devid; ++dev_i) { | 739 | for (dev_i = devid_start; dev_i <= devid; ++dev_i) { |
661 | if (alias) | 740 | if (alias) |
@@ -761,6 +840,15 @@ static int __init init_iommu_all(struct acpi_table_header *table) | |||
761 | h = (struct ivhd_header *)p; | 840 | h = (struct ivhd_header *)p; |
762 | switch (*p) { | 841 | switch (*p) { |
763 | case ACPI_IVHD_TYPE: | 842 | case ACPI_IVHD_TYPE: |
843 | |||
844 | DUMP_printk("IOMMU: device: %02x:%02x.%01x cap: %04x " | ||
845 | "seg: %d flags: %01x info %04x\n", | ||
846 | PCI_BUS(h->devid), PCI_SLOT(h->devid), | ||
847 | PCI_FUNC(h->devid), h->cap_ptr, | ||
848 | h->pci_seg, h->flags, h->info); | ||
849 | DUMP_printk(" mmio-addr: %016llx\n", | ||
850 | h->mmio_phys); | ||
851 | |||
764 | iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL); | 852 | iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL); |
765 | if (iommu == NULL) | 853 | if (iommu == NULL) |
766 | return -ENOMEM; | 854 | return -ENOMEM; |
@@ -868,6 +956,7 @@ static int __init init_exclusion_range(struct ivmd_header *m) | |||
868 | static int __init init_unity_map_range(struct ivmd_header *m) | 956 | static int __init init_unity_map_range(struct ivmd_header *m) |
869 | { | 957 | { |
870 | struct unity_map_entry *e = 0; | 958 | struct unity_map_entry *e = 0; |
959 | char *s; | ||
871 | 960 | ||
872 | e = kzalloc(sizeof(*e), GFP_KERNEL); | 961 | e = kzalloc(sizeof(*e), GFP_KERNEL); |
873 | if (e == NULL) | 962 | if (e == NULL) |
@@ -875,14 +964,19 @@ static int __init init_unity_map_range(struct ivmd_header *m) | |||
875 | 964 | ||
876 | switch (m->type) { | 965 | switch (m->type) { |
877 | default: | 966 | default: |
967 | kfree(e); | ||
968 | return 0; | ||
878 | case ACPI_IVMD_TYPE: | 969 | case ACPI_IVMD_TYPE: |
970 | s = "IVMD_TYPEi\t\t\t"; | ||
879 | e->devid_start = e->devid_end = m->devid; | 971 | e->devid_start = e->devid_end = m->devid; |
880 | break; | 972 | break; |
881 | case ACPI_IVMD_TYPE_ALL: | 973 | case ACPI_IVMD_TYPE_ALL: |
974 | s = "IVMD_TYPE_ALL\t\t"; | ||
882 | e->devid_start = 0; | 975 | e->devid_start = 0; |
883 | e->devid_end = amd_iommu_last_bdf; | 976 | e->devid_end = amd_iommu_last_bdf; |
884 | break; | 977 | break; |
885 | case ACPI_IVMD_TYPE_RANGE: | 978 | case ACPI_IVMD_TYPE_RANGE: |
979 | s = "IVMD_TYPE_RANGE\t\t"; | ||
886 | e->devid_start = m->devid; | 980 | e->devid_start = m->devid; |
887 | e->devid_end = m->aux; | 981 | e->devid_end = m->aux; |
888 | break; | 982 | break; |
@@ -891,6 +985,13 @@ static int __init init_unity_map_range(struct ivmd_header *m) | |||
891 | e->address_end = e->address_start + PAGE_ALIGN(m->range_length); | 985 | e->address_end = e->address_start + PAGE_ALIGN(m->range_length); |
892 | e->prot = m->flags >> 1; | 986 | e->prot = m->flags >> 1; |
893 | 987 | ||
988 | DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x" | ||
989 | " range_start: %016llx range_end: %016llx flags: %x\n", s, | ||
990 | PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start), | ||
991 | PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end), | ||
992 | PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end), | ||
993 | e->address_start, e->address_end, m->flags); | ||
994 | |||
894 | list_add_tail(&e->list, &amd_iommu_unity_map); | 995 | list_add_tail(&e->list, &amd_iommu_unity_map); |
895 | 996 | ||
896 | return 0; | 997 | return 0; |
@@ -1135,9 +1236,6 @@ int __init amd_iommu_init(void) | |||
1135 | 1236 | ||
1136 | enable_iommus(); | 1237 | enable_iommus(); |
1137 | 1238 | ||
1138 | printk(KERN_INFO "AMD IOMMU: aperture size is %d MB\n", | ||
1139 | (1 << (amd_iommu_aperture_order-20))); | ||
1140 | |||
1141 | printk(KERN_INFO "AMD IOMMU: device isolation "); | 1239 | printk(KERN_INFO "AMD IOMMU: device isolation "); |
1142 | if (amd_iommu_isolate) | 1240 | if (amd_iommu_isolate) |
1143 | printk("enabled\n"); | 1241 | printk("enabled\n"); |
@@ -1209,6 +1307,13 @@ void __init amd_iommu_detect(void) | |||
1209 | * | 1307 | * |
1210 | ****************************************************************************/ | 1308 | ****************************************************************************/ |
1211 | 1309 | ||
1310 | static int __init parse_amd_iommu_dump(char *str) | ||
1311 | { | ||
1312 | amd_iommu_dump = true; | ||
1313 | |||
1314 | return 1; | ||
1315 | } | ||
1316 | |||
1212 | static int __init parse_amd_iommu_options(char *str) | 1317 | static int __init parse_amd_iommu_options(char *str) |
1213 | { | 1318 | { |
1214 | for (; *str; ++str) { | 1319 | for (; *str; ++str) { |
@@ -1223,15 +1328,5 @@ static int __init parse_amd_iommu_options(char *str) | |||
1223 | return 1; | 1328 | return 1; |
1224 | } | 1329 | } |
1225 | 1330 | ||
1226 | static int __init parse_amd_iommu_size_options(char *str) | 1331 | __setup("amd_iommu_dump", parse_amd_iommu_dump); |
1227 | { | ||
1228 | unsigned order = PAGE_SHIFT + get_order(memparse(str, &str)); | ||
1229 | |||
1230 | if ((order > 24) && (order < 31)) | ||
1231 | amd_iommu_aperture_order = order; | ||
1232 | |||
1233 | return 1; | ||
1234 | } | ||
1235 | |||
1236 | __setup("amd_iommu=", parse_amd_iommu_options); | 1332 | __setup("amd_iommu=", parse_amd_iommu_options); |
1237 | __setup("amd_iommu_size=", parse_amd_iommu_size_options); | ||