Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec616048 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.infradead.org/iommu-2.6:
  intel_iommu: disable all VT-d PMRs when TXT launched
  intel-iommu: Fix get_domain_for_dev() error path
  intel-iommu: Unlink domain from iommu
  intel-iommu: Fix use after release during device attach
parents df7e1303 51a63e67
Loading
Loading
Loading
Loading
+43 −12
Original line number Diff line number Diff line
@@ -1299,7 +1299,7 @@ static void iommu_detach_domain(struct dmar_domain *domain,
static struct iova_domain reserved_iova_list;
static struct lock_class_key reserved_rbtree_key;

static void dmar_init_reserved_ranges(void)
static int dmar_init_reserved_ranges(void)
{
	struct pci_dev *pdev = NULL;
	struct iova *iova;
@@ -1313,8 +1313,10 @@ static void dmar_init_reserved_ranges(void)
	/* IOAPIC ranges shouldn't be accessed by DMA */
	iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
		IOVA_PFN(IOAPIC_RANGE_END));
	if (!iova)
	if (!iova) {
		printk(KERN_ERR "Reserve IOAPIC range failed\n");
		return -ENODEV;
	}

	/* Reserve all PCI MMIO to avoid peer-to-peer access */
	for_each_pci_dev(pdev) {
@@ -1327,11 +1329,13 @@ static void dmar_init_reserved_ranges(void)
			iova = reserve_iova(&reserved_iova_list,
					    IOVA_PFN(r->start),
					    IOVA_PFN(r->end));
			if (!iova)
			if (!iova) {
				printk(KERN_ERR "Reserve iova failed\n");
				return -ENODEV;
			}
		}

	}
	return 0;
}

static void domain_reserve_special_ranges(struct dmar_domain *domain)
@@ -1835,7 +1839,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)

	ret = iommu_attach_domain(domain, iommu);
	if (ret) {
		domain_exit(domain);
		free_domain_mem(domain);
		goto error;
	}

@@ -2213,7 +2217,7 @@ static int __init iommu_prepare_static_identity_mapping(int hw)
	return 0;
}

int __init init_dmars(void)
static int __init init_dmars(int force_on)
{
	struct dmar_drhd_unit *drhd;
	struct dmar_rmrr_unit *rmrr;
@@ -2393,8 +2397,15 @@ int __init init_dmars(void)
	 *   enable translation
	 */
	for_each_drhd_unit(drhd) {
		if (drhd->ignored)
		if (drhd->ignored) {
			/*
			 * we always have to disable PMRs or DMA may fail on
			 * this device
			 */
			if (force_on)
				iommu_disable_protect_mem_regions(drhd->iommu);
			continue;
		}
		iommu = drhd->iommu;

		iommu_flush_write_buffer(iommu);
@@ -3240,9 +3251,15 @@ static int device_notifier(struct notifier_block *nb,
	if (!domain)
		return 0;

	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
		domain_remove_one_dev_info(domain, pdev);

		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
		    list_empty(&domain->devices))
			domain_exit(domain);
	}

	return 0;
}

@@ -3277,12 +3294,21 @@ int __init intel_iommu_init(void)
	if (no_iommu || dmar_disabled)
		return -ENODEV;

	iommu_init_mempool();
	dmar_init_reserved_ranges();
	if (iommu_init_mempool()) {
		if (force_on)
			panic("tboot: Failed to initialize iommu memory\n");
		return 	-ENODEV;
	}

	if (dmar_init_reserved_ranges()) {
		if (force_on)
			panic("tboot: Failed to reserve iommu ranges\n");
		return 	-ENODEV;
	}

	init_no_remapping_devices();

	ret = init_dmars();
	ret = init_dmars(force_on);
	if (ret) {
		if (force_on)
			panic("tboot: Failed to initialize DMARs\n");
@@ -3391,6 +3417,11 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
		domain->iommu_count--;
		domain_update_iommu_cap(domain);
		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);

		spin_lock_irqsave(&iommu->lock, tmp_flags);
		clear_bit(domain->id, iommu->domain_ids);
		iommu->domains[domain->id] = NULL;
		spin_unlock_irqrestore(&iommu->lock, tmp_flags);
	}

	spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -3607,9 +3638,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,

		pte = dmar_domain->pgd;
		if (dma_pte_present(pte)) {
			free_pgtable_page(dmar_domain->pgd);
			dmar_domain->pgd = (struct dma_pte *)
				phys_to_virt(dma_pte_addr(pte));
			free_pgtable_page(pte);
		}
		dmar_domain->agaw--;
	}