kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/13] iommu bitmap insteads of iommu pointer in dmar_domain
@ 2008-12-02 14:22 Han, Weidong
  2008-12-04 17:12 ` Mark McLoughlin
  0 siblings, 1 reply; 4+ messages in thread
From: Han, Weidong @ 2008-12-02 14:22 UTC (permalink / raw)
  To: 'Avi Kivity', Woodhouse, David, 'Jesse Barnes'
  Cc: 'Joerg Roedel', Kay, Allen M, Yu, Fenghua,
	'kvm@vger.kernel.org',
	'iommu@lists.linux-foundation.org'

[-- Attachment #1: Type: text/plain, Size: 13907 bytes --]

Support dmar_domain own multiple devices from different iommus, which are set in iommu bitmap. add function domain_get_iommu() to get the only one iommu of domain in native VT-d usage.

Signed-off-by: Weidong Han <weidong.han@intel.com>
---
 drivers/pci/intel-iommu.c     |  102 ++++++++++++++++++++++++++++------------
 include/linux/dma_remapping.h |    2 +-
 2 files changed, 72 insertions(+), 32 deletions(-)

diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 5c8baa4..39c5e9d 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -64,6 +64,7 @@ struct deferred_flush_tables {
 	int next;
 	struct iova *iova[HIGH_WATER_MARK];
 	struct dmar_domain *domain[HIGH_WATER_MARK];
+	struct intel_iommu *iommu;
 };
 
 static struct deferred_flush_tables *deferred_flush;
@@ -184,6 +185,21 @@ void free_iova_mem(struct iova *iova)
 	kmem_cache_free(iommu_iova_cache, iova);
 }
 
+/* in native case, each domain is related to only one iommu */
+static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+{
+	struct dmar_drhd_unit *drhd;
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+		if (test_bit(drhd->iommu->seq_id, &domain->iommu_bmp))
+			return drhd->iommu;
+	}
+
+	return NULL;
+}
+
 /* Gets context entry for a given bus and devfn */
 static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
 		u8 bus, u8 devfn)
@@ -324,6 +340,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
 	int level = agaw_to_level(domain->agaw);
 	int offset;
 	unsigned long flags;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
 	BUG_ON(!domain->pgd);
 
@@ -347,7 +364,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
 					flags);
 				return NULL;
 			}
-			__iommu_flush_cache(domain->iommu, tmp_page,
+			__iommu_flush_cache(iommu, tmp_page,
 					PAGE_SIZE);
 			dma_set_pte_addr(*pte, virt_to_phys(tmp_page));
 			/*
@@ -356,7 +373,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
 			 */
 			dma_set_pte_readable(*pte);
 			dma_set_pte_writable(*pte);
-			__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+			__iommu_flush_cache(iommu, pte, sizeof(*pte));
 		}
 		parent = phys_to_virt(dma_pte_addr(*pte));
 		level--;
@@ -393,13 +410,14 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
 static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
 {
 	struct dma_pte *pte = NULL;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
 	/* get last level pte */
 	pte = dma_addr_level_pte(domain, addr, 1);
 
 	if (pte) {
 		dma_clear_pte(*pte);
-		__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+		__iommu_flush_cache(iommu, pte, sizeof(*pte));
 	}
 }
 
@@ -428,6 +446,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
 	int addr_width = agaw_to_width(domain->agaw);
 	struct dma_pte *pte;
 	int total = agaw_to_level(domain->agaw);
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 	int level;
 	u64 tmp;
 
@@ -447,7 +466,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
 				free_pgtable_page(
 					phys_to_virt(dma_pte_addr(*pte)));
 				dma_clear_pte(*pte);
-				__iommu_flush_cache(domain->iommu,
+				__iommu_flush_cache(iommu,
 						pte, sizeof(*pte));
 			}
 			tmp += level_size(level);
@@ -1006,7 +1025,8 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
 
 	set_bit(num, iommu->domain_ids);
 	domain->id = num;
-	domain->iommu = iommu;
+	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+	set_bit(iommu->seq_id, &domain->iommu_bmp);
 	iommu->domains[num] = domain;
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -1016,10 +1036,12 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
 static void iommu_free_domain(struct dmar_domain *domain)
 {
 	unsigned long flags;
+	struct intel_iommu *iommu;
 
-	spin_lock_irqsave(&domain->iommu->lock, flags);
-	clear_bit(domain->id, domain->iommu->domain_ids);
-	spin_unlock_irqrestore(&domain->iommu->lock, flags);
+	iommu = domain_get_iommu(domain);
+	spin_lock_irqsave(&iommu->lock, flags);
+	clear_bit(domain->id, iommu->domain_ids);
+	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 static struct iova_domain reserved_iova_list;
@@ -1098,7 +1120,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
 	domain_reserve_special_ranges(domain);
 
 	/* calculate AGAW */
-	iommu = domain->iommu;
+	iommu = domain_get_iommu(domain);
 	if (guest_width > cap_mgaw(iommu->cap))
 		guest_width = cap_mgaw(iommu->cap);
 	domain->gaw = guest_width;
@@ -1151,7 +1173,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
 		u8 bus, u8 devfn)
 {
 	struct context_entry *context;
-	struct intel_iommu *iommu = domain->iommu;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 	unsigned long flags;
 
 	pr_debug("Set context mapping for %02x:%02x.%d\n",
@@ -1223,8 +1245,9 @@ static int domain_context_mapped(struct dmar_domain *domain,
 {
 	int ret;
 	struct pci_dev *tmp, *parent;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
-	ret = device_context_mapped(domain->iommu,
+	ret = device_context_mapped(iommu,
 		pdev->bus->number, pdev->devfn);
 	if (!ret)
 		return ret;
@@ -1235,17 +1258,17 @@ static int domain_context_mapped(struct dmar_domain *domain,
 	/* Secondary interface's bus number and devfn 0 */
 	parent = pdev->bus->self;
 	while (parent != tmp) {
-		ret = device_context_mapped(domain->iommu, parent->bus->number,
+		ret = device_context_mapped(iommu, parent->bus->number,
 			parent->devfn);
 		if (!ret)
 			return ret;
 		parent = parent->bus->self;
 	}
 	if (tmp->is_pcie)
-		return device_context_mapped(domain->iommu,
+		return device_context_mapped(iommu,
 			tmp->subordinate->number, 0);
 	else
-		return device_context_mapped(domain->iommu,
+		return device_context_mapped(iommu,
 			tmp->bus->number, tmp->devfn);
 }
 
@@ -1257,6 +1280,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
 	struct dma_pte *pte;
 	int index;
 	int addr_width = agaw_to_width(domain->agaw);
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
 	hpa &= (((u64)1) << addr_width) - 1;
 
@@ -1276,7 +1300,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
 		BUG_ON(dma_pte_addr(*pte));
 		dma_set_pte_addr(*pte, start_pfn << VTD_PAGE_SHIFT);
 		dma_set_pte_prot(*pte, prot);
-		__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+		__iommu_flush_cache(iommu, pte, sizeof(*pte));
 		start_pfn++;
 		index++;
 	}
@@ -1285,10 +1309,12 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
 
 static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
 {
-	clear_context_table(domain->iommu, bus, devfn);
-	domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0,
+	struct intel_iommu *iommu = domain_get_iommu(domain);
+
+	clear_context_table(iommu, bus, devfn);
+	iommu->flush.flush_context(iommu, 0, 0, 0,
 					   DMA_CCMD_GLOBAL_INVL, 0);
-	domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0,
+	iommu->flush.flush_iotlb(iommu, 0, 0, 0,
 					 DMA_TLB_GLOBAL_FLUSH, 0);
 }
 
@@ -1827,6 +1853,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	struct iova *iova;
 	int prot = 0;
 	int ret;
+	struct intel_iommu *iommu;
 
 	BUG_ON(dir == DMA_NONE);
 	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
@@ -1835,7 +1862,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	domain = get_valid_domain_for_dev(pdev);
 	if (!domain)
 		return 0;
-
+	iommu = domain_get_iommu(domain);
 	size = aligned_size((u64)paddr, size);
 
 	iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
@@ -1849,7 +1876,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	 * mappings..
 	 */
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-			!cap_zlr(domain->iommu->cap))
+			!cap_zlr(iommu->cap))
 		prot |= DMA_PTE_READ;
 	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
 		prot |= DMA_PTE_WRITE;
@@ -1865,10 +1892,10 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 		goto error;
 
 	/* it's a non-present to present mapping */
-	ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+	ret = iommu_flush_iotlb_psi(iommu, domain->id,
 			start_paddr, size >> VTD_PAGE_SHIFT, 1);
 	if (ret)
-		iommu_flush_write_buffer(domain->iommu);
+		iommu_flush_write_buffer(iommu);
 
 	return start_paddr + ((u64)paddr & (~PAGE_MASK));
 
@@ -1897,7 +1924,7 @@ static void flush_unmaps(void)
 	for (i = 0; i < g_num_of_iommus; i++) {
 		if (deferred_flush[i].next) {
 			struct intel_iommu *iommu =
-				deferred_flush[i].domain[0]->iommu;
+				deferred_flush[i].iommu;
 
 			iommu->flush.flush_iotlb(iommu, 0, 0, 0,
 						 DMA_TLB_GLOBAL_FLUSH, 0);
@@ -1925,16 +1952,19 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
 {
 	unsigned long flags;
 	int next, iommu_id;
+	struct intel_iommu *iommu;
 
 	spin_lock_irqsave(&async_umap_flush_lock, flags);
 	if (list_size == HIGH_WATER_MARK)
 		flush_unmaps();
 
-	iommu_id = dom->iommu->seq_id;
+	iommu = domain_get_iommu(dom);
+	iommu_id = iommu->seq_id;
 
 	next = deferred_flush[iommu_id].next;
 	deferred_flush[iommu_id].domain[next] = dom;
 	deferred_flush[iommu_id].iova[next] = iova;
+	deferred_flush[iommu_id].iommu = iommu;
 	deferred_flush[iommu_id].next++;
 
 	if (!timer_on) {
@@ -1950,6 +1980,7 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
 	unsigned long start_addr;
 	struct iova *iova;
 
@@ -1958,6 +1989,8 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 	domain = find_domain(pdev);
 	BUG_ON(!domain);
 
+	iommu = domain_get_iommu(domain);
+
 	iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
 	if (!iova)
 		return;
@@ -1973,9 +2006,9 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 	/* free page tables */
 	dma_pte_free_pagetable(domain, start_addr, start_addr + size);
 	if (intel_iommu_strict) {
-		if (iommu_flush_iotlb_psi(domain->iommu,
+		if (iommu_flush_iotlb_psi(iommu,
 			domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
-			iommu_flush_write_buffer(domain->iommu);
+			iommu_flush_write_buffer(iommu);
 		/* free iova */
 		__free_iova(&domain->iovad, iova);
 	} else {
@@ -2031,6 +2064,7 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
 	unsigned long start_addr;
 	struct iova *iova;
 	size_t size = 0;
@@ -2045,6 +2079,9 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
 	if (!iova)
 		return;
+
+	iommu = domain_get_iommu(domain);
+
 	for_each_sg(sglist, sg, nelems, i) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
 		size += aligned_size((u64)addr, sg->length);
@@ -2057,9 +2094,9 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	/* free page tables */
 	dma_pte_free_pagetable(domain, start_addr, start_addr + size);
 
-	if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+	if (iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
 			size >> VTD_PAGE_SHIFT, 0))
-		iommu_flush_write_buffer(domain->iommu);
+		iommu_flush_write_buffer(iommu);
 
 	/* free iova */
 	__free_iova(&domain->iovad, iova);
@@ -2086,6 +2123,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
 	size_t size = 0;
 	int prot = 0;
 	size_t offset = 0;
@@ -2102,6 +2140,8 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	if (!domain)
 		return 0;
 
+	iommu = domain_get_iommu(domain);
+
 	for_each_sg(sglist, sg, nelems, i) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
 		addr = (void *)virt_to_phys(addr);
@@ -2119,7 +2159,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	 * mappings..
 	 */
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-			!cap_zlr(domain->iommu->cap))
+			!cap_zlr(iommu->cap))
 		prot |= DMA_PTE_READ;
 	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
 		prot |= DMA_PTE_WRITE;
@@ -2151,9 +2191,9 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	}
 
 	/* it's a non-present to present mapping */
-	if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
+	if (iommu_flush_iotlb_psi(iommu, domain->id,
 			start_addr, offset >> VTD_PAGE_SHIFT, 1))
-		iommu_flush_write_buffer(domain->iommu);
+		iommu_flush_write_buffer(iommu);
 	return nelems;
 }
 
diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h
index 952df39..66f7887 100644
--- a/include/linux/dma_remapping.h
+++ b/include/linux/dma_remapping.h
@@ -115,7 +115,7 @@ struct intel_iommu;
 
 struct dmar_domain {
 	int	id;			/* domain id */
-	struct intel_iommu *iommu;	/* back pointer to owning iommu */
+	unsigned long iommu_bmp;	/* bitmap of iommus this domain uses*/
 
 	struct list_head devices; 	/* all devices' list */
 	struct iova_domain iovad;	/* iova's that belong to this domain */
-- 
1.5.1

[-- Attachment #2: 0001-iommu-bitmap-insteads-of-iommu-pointer.patch --]
[-- Type: application/octet-stream, Size: 13555 bytes --]

From c029088744902dc57816ed8fdea86368efd03ed4 Mon Sep 17 00:00:00 2001
From: Weidong Han <weidong.han@intel.com>
Date: Tue, 2 Dec 2008 13:44:22 +0800
Subject: [PATCH] iommu bitmap insteads of iommu pointer in dmar_domain 


Signed-off-by: Weidong Han <weidong.han@intel.com>
---
 drivers/pci/intel-iommu.c     |  102 ++++++++++++++++++++++++++++------------
 include/linux/dma_remapping.h |    2 +-
 2 files changed, 72 insertions(+), 32 deletions(-)

diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 5c8baa4..39c5e9d 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -64,6 +64,7 @@ struct deferred_flush_tables {
 	int next;
 	struct iova *iova[HIGH_WATER_MARK];
 	struct dmar_domain *domain[HIGH_WATER_MARK];
+	struct intel_iommu *iommu;
 };
 
 static struct deferred_flush_tables *deferred_flush;
@@ -184,6 +185,21 @@ void free_iova_mem(struct iova *iova)
 	kmem_cache_free(iommu_iova_cache, iova);
 }
 
+/* in native case, each domain is related to only one iommu */
+static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+{
+	struct dmar_drhd_unit *drhd;
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+		if (test_bit(drhd->iommu->seq_id, &domain->iommu_bmp))
+			return drhd->iommu;
+	}
+
+	return NULL;
+}
+
 /* Gets context entry for a given bus and devfn */
 static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
 		u8 bus, u8 devfn)
@@ -324,6 +340,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
 	int level = agaw_to_level(domain->agaw);
 	int offset;
 	unsigned long flags;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
 	BUG_ON(!domain->pgd);
 
@@ -347,7 +364,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
 					flags);
 				return NULL;
 			}
-			__iommu_flush_cache(domain->iommu, tmp_page,
+			__iommu_flush_cache(iommu, tmp_page,
 					PAGE_SIZE);
 			dma_set_pte_addr(*pte, virt_to_phys(tmp_page));
 			/*
@@ -356,7 +373,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
 			 */
 			dma_set_pte_readable(*pte);
 			dma_set_pte_writable(*pte);
-			__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+			__iommu_flush_cache(iommu, pte, sizeof(*pte));
 		}
 		parent = phys_to_virt(dma_pte_addr(*pte));
 		level--;
@@ -393,13 +410,14 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
 static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
 {
 	struct dma_pte *pte = NULL;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
 	/* get last level pte */
 	pte = dma_addr_level_pte(domain, addr, 1);
 
 	if (pte) {
 		dma_clear_pte(*pte);
-		__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+		__iommu_flush_cache(iommu, pte, sizeof(*pte));
 	}
 }
 
@@ -428,6 +446,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
 	int addr_width = agaw_to_width(domain->agaw);
 	struct dma_pte *pte;
 	int total = agaw_to_level(domain->agaw);
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 	int level;
 	u64 tmp;
 
@@ -447,7 +466,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
 				free_pgtable_page(
 					phys_to_virt(dma_pte_addr(*pte)));
 				dma_clear_pte(*pte);
-				__iommu_flush_cache(domain->iommu,
+				__iommu_flush_cache(iommu,
 						pte, sizeof(*pte));
 			}
 			tmp += level_size(level);
@@ -1006,7 +1025,8 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
 
 	set_bit(num, iommu->domain_ids);
 	domain->id = num;
-	domain->iommu = iommu;
+	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+	set_bit(iommu->seq_id, &domain->iommu_bmp);
 	iommu->domains[num] = domain;
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -1016,10 +1036,12 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
 static void iommu_free_domain(struct dmar_domain *domain)
 {
 	unsigned long flags;
+	struct intel_iommu *iommu;
 
-	spin_lock_irqsave(&domain->iommu->lock, flags);
-	clear_bit(domain->id, domain->iommu->domain_ids);
-	spin_unlock_irqrestore(&domain->iommu->lock, flags);
+	iommu = domain_get_iommu(domain);
+	spin_lock_irqsave(&iommu->lock, flags);
+	clear_bit(domain->id, iommu->domain_ids);
+	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 static struct iova_domain reserved_iova_list;
@@ -1098,7 +1120,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
 	domain_reserve_special_ranges(domain);
 
 	/* calculate AGAW */
-	iommu = domain->iommu;
+	iommu = domain_get_iommu(domain);
 	if (guest_width > cap_mgaw(iommu->cap))
 		guest_width = cap_mgaw(iommu->cap);
 	domain->gaw = guest_width;
@@ -1151,7 +1173,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
 		u8 bus, u8 devfn)
 {
 	struct context_entry *context;
-	struct intel_iommu *iommu = domain->iommu;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 	unsigned long flags;
 
 	pr_debug("Set context mapping for %02x:%02x.%d\n",
@@ -1223,8 +1245,9 @@ static int domain_context_mapped(struct dmar_domain *domain,
 {
 	int ret;
 	struct pci_dev *tmp, *parent;
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
-	ret = device_context_mapped(domain->iommu,
+	ret = device_context_mapped(iommu,
 		pdev->bus->number, pdev->devfn);
 	if (!ret)
 		return ret;
@@ -1235,17 +1258,17 @@ static int domain_context_mapped(struct dmar_domain *domain,
 	/* Secondary interface's bus number and devfn 0 */
 	parent = pdev->bus->self;
 	while (parent != tmp) {
-		ret = device_context_mapped(domain->iommu, parent->bus->number,
+		ret = device_context_mapped(iommu, parent->bus->number,
 			parent->devfn);
 		if (!ret)
 			return ret;
 		parent = parent->bus->self;
 	}
 	if (tmp->is_pcie)
-		return device_context_mapped(domain->iommu,
+		return device_context_mapped(iommu,
 			tmp->subordinate->number, 0);
 	else
-		return device_context_mapped(domain->iommu,
+		return device_context_mapped(iommu,
 			tmp->bus->number, tmp->devfn);
 }
 
@@ -1257,6 +1280,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
 	struct dma_pte *pte;
 	int index;
 	int addr_width = agaw_to_width(domain->agaw);
+	struct intel_iommu *iommu = domain_get_iommu(domain);
 
 	hpa &= (((u64)1) << addr_width) - 1;
 
@@ -1276,7 +1300,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
 		BUG_ON(dma_pte_addr(*pte));
 		dma_set_pte_addr(*pte, start_pfn << VTD_PAGE_SHIFT);
 		dma_set_pte_prot(*pte, prot);
-		__iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+		__iommu_flush_cache(iommu, pte, sizeof(*pte));
 		start_pfn++;
 		index++;
 	}
@@ -1285,10 +1309,12 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
 
 static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
 {
-	clear_context_table(domain->iommu, bus, devfn);
-	domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0,
+	struct intel_iommu *iommu = domain_get_iommu(domain);
+
+	clear_context_table(iommu, bus, devfn);
+	iommu->flush.flush_context(iommu, 0, 0, 0,
 					   DMA_CCMD_GLOBAL_INVL, 0);
-	domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0,
+	iommu->flush.flush_iotlb(iommu, 0, 0, 0,
 					 DMA_TLB_GLOBAL_FLUSH, 0);
 }
 
@@ -1827,6 +1853,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	struct iova *iova;
 	int prot = 0;
 	int ret;
+	struct intel_iommu *iommu;
 
 	BUG_ON(dir == DMA_NONE);
 	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
@@ -1835,7 +1862,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	domain = get_valid_domain_for_dev(pdev);
 	if (!domain)
 		return 0;
-
+	iommu = domain_get_iommu(domain);
 	size = aligned_size((u64)paddr, size);
 
 	iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
@@ -1849,7 +1876,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	 * mappings..
 	 */
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-			!cap_zlr(domain->iommu->cap))
+			!cap_zlr(iommu->cap))
 		prot |= DMA_PTE_READ;
 	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
 		prot |= DMA_PTE_WRITE;
@@ -1865,10 +1892,10 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 		goto error;
 
 	/* it's a non-present to present mapping */
-	ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+	ret = iommu_flush_iotlb_psi(iommu, domain->id,
 			start_paddr, size >> VTD_PAGE_SHIFT, 1);
 	if (ret)
-		iommu_flush_write_buffer(domain->iommu);
+		iommu_flush_write_buffer(iommu);
 
 	return start_paddr + ((u64)paddr & (~PAGE_MASK));
 
@@ -1897,7 +1924,7 @@ static void flush_unmaps(void)
 	for (i = 0; i < g_num_of_iommus; i++) {
 		if (deferred_flush[i].next) {
 			struct intel_iommu *iommu =
-				deferred_flush[i].domain[0]->iommu;
+				deferred_flush[i].iommu;
 
 			iommu->flush.flush_iotlb(iommu, 0, 0, 0,
 						 DMA_TLB_GLOBAL_FLUSH, 0);
@@ -1925,16 +1952,19 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
 {
 	unsigned long flags;
 	int next, iommu_id;
+	struct intel_iommu *iommu;
 
 	spin_lock_irqsave(&async_umap_flush_lock, flags);
 	if (list_size == HIGH_WATER_MARK)
 		flush_unmaps();
 
-	iommu_id = dom->iommu->seq_id;
+	iommu = domain_get_iommu(dom);
+	iommu_id = iommu->seq_id;
 
 	next = deferred_flush[iommu_id].next;
 	deferred_flush[iommu_id].domain[next] = dom;
 	deferred_flush[iommu_id].iova[next] = iova;
+	deferred_flush[iommu_id].iommu = iommu;
 	deferred_flush[iommu_id].next++;
 
 	if (!timer_on) {
@@ -1950,6 +1980,7 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
 	unsigned long start_addr;
 	struct iova *iova;
 
@@ -1958,6 +1989,8 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 	domain = find_domain(pdev);
 	BUG_ON(!domain);
 
+	iommu = domain_get_iommu(domain);
+
 	iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
 	if (!iova)
 		return;
@@ -1973,9 +2006,9 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 	/* free page tables */
 	dma_pte_free_pagetable(domain, start_addr, start_addr + size);
 	if (intel_iommu_strict) {
-		if (iommu_flush_iotlb_psi(domain->iommu,
+		if (iommu_flush_iotlb_psi(iommu,
 			domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
-			iommu_flush_write_buffer(domain->iommu);
+			iommu_flush_write_buffer(iommu);
 		/* free iova */
 		__free_iova(&domain->iovad, iova);
 	} else {
@@ -2031,6 +2064,7 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
 	unsigned long start_addr;
 	struct iova *iova;
 	size_t size = 0;
@@ -2045,6 +2079,9 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
 	if (!iova)
 		return;
+
+	iommu = domain_get_iommu(domain);
+
 	for_each_sg(sglist, sg, nelems, i) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
 		size += aligned_size((u64)addr, sg->length);
@@ -2057,9 +2094,9 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	/* free page tables */
 	dma_pte_free_pagetable(domain, start_addr, start_addr + size);
 
-	if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+	if (iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
 			size >> VTD_PAGE_SHIFT, 0))
-		iommu_flush_write_buffer(domain->iommu);
+		iommu_flush_write_buffer(iommu);
 
 	/* free iova */
 	__free_iova(&domain->iovad, iova);
@@ -2086,6 +2123,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
+	struct intel_iommu *iommu;
 	size_t size = 0;
 	int prot = 0;
 	size_t offset = 0;
@@ -2102,6 +2140,8 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	if (!domain)
 		return 0;
 
+	iommu = domain_get_iommu(domain);
+
 	for_each_sg(sglist, sg, nelems, i) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
 		addr = (void *)virt_to_phys(addr);
@@ -2119,7 +2159,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	 * mappings..
 	 */
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-			!cap_zlr(domain->iommu->cap))
+			!cap_zlr(iommu->cap))
 		prot |= DMA_PTE_READ;
 	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
 		prot |= DMA_PTE_WRITE;
@@ -2151,9 +2191,9 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 	}
 
 	/* it's a non-present to present mapping */
-	if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
+	if (iommu_flush_iotlb_psi(iommu, domain->id,
 			start_addr, offset >> VTD_PAGE_SHIFT, 1))
-		iommu_flush_write_buffer(domain->iommu);
+		iommu_flush_write_buffer(iommu);
 	return nelems;
 }
 
diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h
index 952df39..66f7887 100644
--- a/include/linux/dma_remapping.h
+++ b/include/linux/dma_remapping.h
@@ -115,7 +115,7 @@ struct intel_iommu;
 
 struct dmar_domain {
 	int	id;			/* domain id */
-	struct intel_iommu *iommu;	/* back pointer to owning iommu */
+	unsigned long iommu_bmp;	/* bitmap of iommus this domain uses*/
 
 	struct list_head devices; 	/* all devices' list */
 	struct iova_domain iovad;	/* iova's that belong to this domain */
-- 
1.5.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-12-05 16:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-02 14:22 [PATCH 01/13] iommu bitmap insteads of iommu pointer in dmar_domain Han, Weidong
2008-12-04 17:12 ` Mark McLoughlin
2008-12-05  0:52   ` Han, Weidong
2008-12-05 16:42   ` Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).