diff options
-rw-r--r-- | Documentation/Intel-IOMMU.txt | 5 | ||||
-rw-r--r-- | arch/x86/kernel/e820_64.c | 19 | ||||
-rw-r--r-- | arch/x86_64/Kconfig | 19 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 33 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.h | 7 |
5 files changed, 79 insertions, 4 deletions
diff --git a/Documentation/Intel-IOMMU.txt b/Documentation/Intel-IOMMU.txt index aba7722c2935..c2321903aa09 100644 --- a/Documentation/Intel-IOMMU.txt +++ b/Documentation/Intel-IOMMU.txt | |||
@@ -57,6 +57,11 @@ Graphics Problems? | |||
57 | If you encounter issues with graphics devices, you can try adding | 57 | If you encounter issues with graphics devices, you can try adding |
58 | option intel_iommu=igfx_off to turn off the integrated graphics engine. | 58 | option intel_iommu=igfx_off to turn off the integrated graphics engine. |
59 | 59 | ||
60 | If it happens to be a PCI device included in the INCLUDE_ALL Engine, | ||
61 | then try enabling CONFIG_DMAR_GFX_WA to setup a 1-1 map. We hear | ||
62 | graphics drivers may be in process of using DMA api's in the near | ||
63 | future and at that time this option can be yanked out. | ||
64 | |||
60 | Some exceptions to IOVA | 65 | Some exceptions to IOVA |
61 | ----------------------- | 66 | ----------------------- |
62 | Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff). | 67 | Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff). |
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 57616865d8a0..1ca228b06a20 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c | |||
@@ -729,3 +729,22 @@ __init void e820_setup_gap(void) | |||
729 | printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", | 729 | printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", |
730 | pci_mem_start, gapstart, gapsize); | 730 | pci_mem_start, gapstart, gapsize); |
731 | } | 731 | } |
732 | |||
733 | int __init arch_get_ram_range(int slot, u64 *addr, u64 *size) | ||
734 | { | ||
735 | int i; | ||
736 | |||
737 | if (slot < 0 || slot >= e820.nr_map) | ||
738 | return -1; | ||
739 | for (i = slot; i < e820.nr_map; i++) { | ||
740 | if (e820.map[i].type != E820_RAM) | ||
741 | continue; | ||
742 | break; | ||
743 | } | ||
744 | if (i == e820.nr_map || e820.map[i].addr > (max_pfn << PAGE_SHIFT)) | ||
745 | return -1; | ||
746 | *addr = e820.map[i].addr; | ||
747 | *size = min_t(u64, e820.map[i].size + e820.map[i].addr, | ||
748 | max_pfn << PAGE_SHIFT) - *addr; | ||
749 | return i + 1; | ||
750 | } | ||
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 5c9aaed589a5..5cf941774347 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -755,11 +755,22 @@ config DMAR | |||
755 | depends on PCI_MSI && ACPI && EXPERIMENTAL | 755 | depends on PCI_MSI && ACPI && EXPERIMENTAL |
756 | default y | 756 | default y |
757 | help | 757 | help |
758 | DMA remapping(DMAR) devices support enables independent address | 758 | DMA remapping (DMAR) devices support enables independent address |
759 | translations for Direct Memory Access(DMA) from Devices. | 759 | translations for Direct Memory Access (DMA) from devices. |
760 | These DMA remapping devices are reported via ACPI tables | 760 | These DMA remapping devices are reported via ACPI tables |
761 | and includes pci device scope covered by these DMA | 761 | and include PCI device scope covered by these DMA |
762 | remapping device. | 762 | remapping devices. |
763 | |||
764 | config DMAR_GFX_WA | ||
765 | bool "Support for Graphics workaround" | ||
766 | depends on DMAR | ||
767 | default y | ||
768 | help | ||
769 | Current Graphics drivers tend to use physical address | ||
770 | for DMA and avoid using DMA APIs. Setting this config | ||
771 | option permits the IOMMU driver to set a unity map for | ||
772 | all the OS-visible memory. Hence the driver can continue | ||
773 | to use physical addresses for DMA. | ||
763 | 774 | ||
764 | source "drivers/pci/pcie/Kconfig" | 775 | source "drivers/pci/pcie/Kconfig" |
765 | 776 | ||
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 358dd406fe21..4905e0e3a644 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1602,6 +1602,36 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | |||
1602 | rmrr->end_address + 1); | 1602 | rmrr->end_address + 1); |
1603 | } | 1603 | } |
1604 | 1604 | ||
1605 | #ifdef CONFIG_DMAR_GFX_WA | ||
1606 | extern int arch_get_ram_range(int slot, u64 *addr, u64 *size); | ||
1607 | static void __init iommu_prepare_gfx_mapping(void) | ||
1608 | { | ||
1609 | struct pci_dev *pdev = NULL; | ||
1610 | u64 base, size; | ||
1611 | int slot; | ||
1612 | int ret; | ||
1613 | |||
1614 | for_each_pci_dev(pdev) { | ||
1615 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO || | ||
1616 | !IS_GFX_DEVICE(pdev)) | ||
1617 | continue; | ||
1618 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | ||
1619 | pci_name(pdev)); | ||
1620 | slot = arch_get_ram_range(0, &base, &size); | ||
1621 | while (slot >= 0) { | ||
1622 | ret = iommu_prepare_identity_map(pdev, | ||
1623 | base, base + size); | ||
1624 | if (ret) | ||
1625 | goto error; | ||
1626 | slot = arch_get_ram_range(slot, &base, &size); | ||
1627 | } | ||
1628 | continue; | ||
1629 | error: | ||
1630 | printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | ||
1631 | } | ||
1632 | } | ||
1633 | #endif | ||
1634 | |||
1605 | int __init init_dmars(void) | 1635 | int __init init_dmars(void) |
1606 | { | 1636 | { |
1607 | struct dmar_drhd_unit *drhd; | 1637 | struct dmar_drhd_unit *drhd; |
@@ -1665,6 +1695,8 @@ int __init init_dmars(void) | |||
1665 | } | 1695 | } |
1666 | } | 1696 | } |
1667 | 1697 | ||
1698 | iommu_prepare_gfx_mapping(); | ||
1699 | |||
1668 | /* | 1700 | /* |
1669 | * for each drhd | 1701 | * for each drhd |
1670 | * enable fault log | 1702 | * enable fault log |
@@ -2176,3 +2208,4 @@ int __init intel_iommu_init(void) | |||
2176 | dma_ops = &intel_dma_ops; | 2208 | dma_ops = &intel_dma_ops; |
2177 | return 0; | 2209 | return 0; |
2178 | } | 2210 | } |
2211 | |||
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 71dda6b56ffa..ee88dd2400cb 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h | |||
@@ -315,4 +315,11 @@ struct intel_iommu { | |||
315 | struct sys_device sysdev; | 315 | struct sys_device sysdev; |
316 | }; | 316 | }; |
317 | 317 | ||
318 | #ifndef CONFIG_DMAR_GFX_WA | ||
319 | static inline void iommu_prepare_gfx_mapping(void) | ||
320 | { | ||
321 | return; | ||
322 | } | ||
323 | #endif /* !CONFIG_DMAR_GFX_WA */ | ||
324 | |||
318 | #endif | 325 | #endif |