diff options
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 46 | 
1 files changed, 42 insertions, 4 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0badfa48b32..b9d09115788 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1827,10 +1827,17 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,  			if (!pte)  				return -ENOMEM;  			/* It is large page*/ -			if (largepage_lvl > 1) +			if (largepage_lvl > 1) {  				pteval |= DMA_PTE_LARGE_PAGE; -			else +				/* Ensure that old small page tables are removed to make room +				   for superpage, if they exist. */ +				dma_pte_clear_range(domain, iov_pfn, +						    iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); +				dma_pte_free_pagetable(domain, iov_pfn, +						       iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); +			} else {  				pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; +			}  		}  		/* We don't need lock here, nobody else @@ -2320,8 +2327,39 @@ static int domain_add_dev_info(struct dmar_domain *domain,  	return 0;  } +static bool device_has_rmrr(struct pci_dev *dev) +{ +	struct dmar_rmrr_unit *rmrr; +	int i; + +	for_each_rmrr_units(rmrr) { +		for (i = 0; i < rmrr->devices_cnt; i++) { +			/* +			 * Return TRUE if this RMRR contains the device that +			 * is passed in. +			 */ +			if (rmrr->devices[i] == dev) +				return true; +		} +	} +	return false; +} +  static int iommu_should_identity_map(struct pci_dev *pdev, int startup)  { + +	/* +	 * We want to prevent any device associated with an RMRR from +	 * getting placed into the SI Domain. This is done because +	 * problems exist when devices are moved in and out of domains +	 * and their respective RMRR info is lost. We exempt USB devices +	 * from this process due to their usage of RMRRs that are known +	 * to not be needed after BIOS hand-off to OS. +	 */ +	if (device_has_rmrr(pdev) && +	    (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) +		return 0; +  	if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))  		return 1; @@ -4196,7 +4234,7 @@ static struct iommu_ops intel_iommu_ops = {  	.pgsize_bitmap	= INTEL_IOMMU_PGSIZES,  }; -static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) +static void quirk_iommu_rwbf(struct pci_dev *dev)  {  	/*  	 * Mobile 4 Series Chipset neglects to set RWBF capability, @@ -4224,7 +4262,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);  #define GGC_MEMORY_SIZE_3M_VT	(0xa << 8)  #define GGC_MEMORY_SIZE_4M_VT	(0xb << 8) -static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev) +static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)  {  	unsigned short ggc;  |