diff options
Diffstat (limited to 'drivers/pci/intel-iommu.c')
| -rw-r--r-- | drivers/pci/intel-iommu.c | 117 |
1 files changed, 70 insertions, 47 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index c3ceebb5be84..4789f8e8bf7a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -71,6 +71,49 @@ | |||
| 71 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) | 71 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) |
| 72 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) | 72 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) |
| 73 | 73 | ||
| 74 | /* page table handling */ | ||
| 75 | #define LEVEL_STRIDE (9) | ||
| 76 | #define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) | ||
| 77 | |||
| 78 | static inline int agaw_to_level(int agaw) | ||
| 79 | { | ||
| 80 | return agaw + 2; | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline int agaw_to_width(int agaw) | ||
| 84 | { | ||
| 85 | return 30 + agaw * LEVEL_STRIDE; | ||
| 86 | } | ||
| 87 | |||
| 88 | static inline int width_to_agaw(int width) | ||
| 89 | { | ||
| 90 | return (width - 30) / LEVEL_STRIDE; | ||
| 91 | } | ||
| 92 | |||
| 93 | static inline unsigned int level_to_offset_bits(int level) | ||
| 94 | { | ||
| 95 | return (level - 1) * LEVEL_STRIDE; | ||
| 96 | } | ||
| 97 | |||
| 98 | static inline int pfn_level_offset(unsigned long pfn, int level) | ||
| 99 | { | ||
| 100 | return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; | ||
| 101 | } | ||
| 102 | |||
| 103 | static inline unsigned long level_mask(int level) | ||
| 104 | { | ||
| 105 | return -1UL << level_to_offset_bits(level); | ||
| 106 | } | ||
| 107 | |||
| 108 | static inline unsigned long level_size(int level) | ||
| 109 | { | ||
| 110 | return 1UL << level_to_offset_bits(level); | ||
| 111 | } | ||
| 112 | |||
| 113 | static inline unsigned long align_to_level(unsigned long pfn, int level) | ||
| 114 | { | ||
| 115 | return (pfn + level_size(level) - 1) & level_mask(level); | ||
| 116 | } | ||
| 74 | 117 | ||
| 75 | /* VT-d pages must always be _smaller_ than MM pages. Otherwise things | 118 | /* VT-d pages must always be _smaller_ than MM pages. Otherwise things |
| 76 | are never going to work. */ | 119 | are never going to work. */ |
| @@ -434,8 +477,6 @@ void free_iova_mem(struct iova *iova) | |||
| 434 | } | 477 | } |
| 435 | 478 | ||
| 436 | 479 | ||
| 437 | static inline int width_to_agaw(int width); | ||
| 438 | |||
| 439 | static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) | 480 | static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) |
| 440 | { | 481 | { |
| 441 | unsigned long sagaw; | 482 | unsigned long sagaw; |
| @@ -646,51 +687,6 @@ out: | |||
| 646 | spin_unlock_irqrestore(&iommu->lock, flags); | 687 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 647 | } | 688 | } |
| 648 | 689 | ||
| 649 | /* page table handling */ | ||
| 650 | #define LEVEL_STRIDE (9) | ||
| 651 | #define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) | ||
| 652 | |||
| 653 | static inline int agaw_to_level(int agaw) | ||
| 654 | { | ||
| 655 | return agaw + 2; | ||
| 656 | } | ||
| 657 | |||
| 658 | static inline int agaw_to_width(int agaw) | ||
| 659 | { | ||
| 660 | return 30 + agaw * LEVEL_STRIDE; | ||
| 661 | |||
| 662 | } | ||
| 663 | |||
| 664 | static inline int width_to_agaw(int width) | ||
| 665 | { | ||
| 666 | return (width - 30) / LEVEL_STRIDE; | ||
| 667 | } | ||
| 668 | |||
| 669 | static inline unsigned int level_to_offset_bits(int level) | ||
| 670 | { | ||
| 671 | return (level - 1) * LEVEL_STRIDE; | ||
| 672 | } | ||
| 673 | |||
| 674 | static inline int pfn_level_offset(unsigned long pfn, int level) | ||
| 675 | { | ||
| 676 | return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; | ||
| 677 | } | ||
| 678 | |||
| 679 | static inline unsigned long level_mask(int level) | ||
| 680 | { | ||
| 681 | return -1UL << level_to_offset_bits(level); | ||
| 682 | } | ||
| 683 | |||
| 684 | static inline unsigned long level_size(int level) | ||
| 685 | { | ||
| 686 | return 1UL << level_to_offset_bits(level); | ||
| 687 | } | ||
| 688 | |||
| 689 | static inline unsigned long align_to_level(unsigned long pfn, int level) | ||
| 690 | { | ||
| 691 | return (pfn + level_size(level) - 1) & level_mask(level); | ||
| 692 | } | ||
| 693 | |||
| 694 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, | 690 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, |
| 695 | unsigned long pfn) | 691 | unsigned long pfn) |
| 696 | { | 692 | { |
| @@ -3761,6 +3757,33 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) | |||
| 3761 | 3757 | ||
| 3762 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); | 3758 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); |
| 3763 | 3759 | ||
| 3760 | #define GGC 0x52 | ||
| 3761 | #define GGC_MEMORY_SIZE_MASK (0xf << 8) | ||
| 3762 | #define GGC_MEMORY_SIZE_NONE (0x0 << 8) | ||
| 3763 | #define GGC_MEMORY_SIZE_1M (0x1 << 8) | ||
| 3764 | #define GGC_MEMORY_SIZE_2M (0x3 << 8) | ||
| 3765 | #define GGC_MEMORY_VT_ENABLED (0x8 << 8) | ||
| 3766 | #define GGC_MEMORY_SIZE_2M_VT (0x9 << 8) | ||
| 3767 | #define GGC_MEMORY_SIZE_3M_VT (0xa << 8) | ||
| 3768 | #define GGC_MEMORY_SIZE_4M_VT (0xb << 8) | ||
| 3769 | |||
| 3770 | static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev) | ||
| 3771 | { | ||
| 3772 | unsigned short ggc; | ||
| 3773 | |||
| 3774 | if (pci_read_config_word(dev, GGC, &ggc)) | ||
| 3775 | return; | ||
| 3776 | |||
| 3777 | if (!(ggc & GGC_MEMORY_VT_ENABLED)) { | ||
| 3778 | printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); | ||
| 3779 | dmar_map_gfx = 0; | ||
| 3780 | } | ||
| 3781 | } | ||
| 3782 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt); | ||
| 3783 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt); | ||
| 3784 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); | ||
| 3785 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); | ||
| 3786 | |||
| 3764 | /* On Tylersburg chipsets, some BIOSes have been known to enable the | 3787 | /* On Tylersburg chipsets, some BIOSes have been known to enable the |
| 3765 | ISOCH DMAR unit for the Azalia sound device, but not give it any | 3788 | ISOCH DMAR unit for the Azalia sound device, but not give it any |
| 3766 | TLB entries, which causes it to deadlock. Check for that. We do | 3789 | TLB entries, which causes it to deadlock. Check for that. We do |
