changeset 13002:f246a5b54a71

6964516 Intel IOMMU code should use passthrough for unity mappings 6968824 Intel IOMMU ACPI DMAR table code can call kmem_free with the wrong size.
author Frank Van Der Linden <frank.van.der.linden@oracle.com>
date Mon, 02 Aug 2010 13:17:35 -0700
parents 1e6b26d10a55
children b4084e8201cf
files usr/src/uts/i86pc/io/immu_dmar.c usr/src/uts/i86pc/io/immu_dvma.c
diffstat 2 files changed, 26 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/i86pc/io/immu_dmar.c	Mon Aug 02 16:06:35 2010 -0400
+++ b/usr/src/uts/i86pc/io/immu_dmar.c	Mon Aug 02 13:17:35 2010 -0700
@@ -807,8 +807,8 @@
 	}
 
 	/* free strings */
-	kmem_free(tbl->tbl_oem_tblid, TBL_OEM_ID_SZ + 1);
-	kmem_free(tbl->tbl_oem_id, TBL_OEM_TBLID_SZ + 1);
+	kmem_free(tbl->tbl_oem_tblid, TBL_OEM_TBLID_SZ + 1);
+	kmem_free(tbl->tbl_oem_id, TBL_OEM_ID_SZ + 1);
 	tbl->tbl_raw = NULL; /* raw ACPI table doesn't have to be freed */
 	mutex_destroy(&(tbl->tbl_lock));
 	kmem_free(tbl, sizeof (dmar_table_t));
--- a/usr/src/uts/i86pc/io/immu_dvma.c	Mon Aug 02 16:06:35 2010 -0400
+++ b/usr/src/uts/i86pc/io/immu_dvma.c	Mon Aug 02 13:17:35 2010 -0700
@@ -1306,7 +1306,14 @@
 	ASSERT(domain->dom_pgtable_root);
 	pgtable_zero(immu, domain->dom_pgtable_root);
 
-	map_unity_domain(domain);
+	/*
+	 * Only map all physical memory in to the unity domain
+	 * if passthrough is not supported. If it is supported,
+	 * passthrough is set in the context entry instead.
+	 */
+	if (!IMMU_ECAP_GET_PT(immu->immu_regs_excap))
+		map_unity_domain(domain);
+
 
 	/*
 	 * put it on the system-wide UNITY domain list
@@ -1506,7 +1513,6 @@
 			ASSERT(CONT_GET_P(hw_cent));
 			ASSERT(CONT_GET_DID(hw_cent) == domain->dom_did);
 			ASSERT(CONT_GET_AW(hw_cent) == immu->immu_dvma_agaw);
-			ASSERT(CONT_GET_TTYPE(hw_cent) == TTYPE_XLATE_ONLY);
 			ASSERT(CONT_GET_ASR(hw_cent) ==
 			    pgtable_root->hwpg_paddr);
 			rw_exit(&(immu->immu_ctx_rwlock));
@@ -1542,7 +1548,6 @@
 		ASSERT(CONT_GET_DID(hw_cent) ==
 		    immu->immu_unity_domain->dom_did);
 		ASSERT(CONT_GET_AW(hw_cent) == immu->immu_dvma_agaw);
-		ASSERT(CONT_GET_TTYPE(hw_cent) == TTYPE_XLATE_ONLY);
 		ASSERT(CONT_GET_ASR(hw_cent) ==
 		    unity_pgtable_root->hwpg_paddr);
 
@@ -1562,8 +1567,12 @@
 		CONT_SET_DID(hw_cent, domain->dom_did);
 		CONT_SET_AW(hw_cent, immu->immu_dvma_agaw);
 		CONT_SET_ASR(hw_cent, pgtable_root->hwpg_paddr);
-		/*LINTED*/
-		CONT_SET_TTYPE(hw_cent, TTYPE_XLATE_ONLY);
+		if (domain->dom_did == IMMU_UNITY_DID &&
+		    IMMU_ECAP_GET_PT(immu->immu_regs_excap))
+			CONT_SET_TTYPE(hw_cent, TTYPE_PASSTHRU);
+		else
+			/*LINTED*/
+			CONT_SET_TTYPE(hw_cent, TTYPE_XLATE_ONLY);
 		CONT_SET_P(hw_cent);
 		immu_regs_cpu_flush(immu, (caddr_t)hw_cent, sizeof (hw_rce_t));
 	}
@@ -1608,8 +1617,11 @@
 			    immu->immu_unity_domain->dom_did);
 			CONT_SET_AW(hw_cent, immu->immu_dvma_agaw);
 			CONT_SET_ASR(hw_cent, pgtable_root->hwpg_paddr);
-			/*LINTED*/
-			CONT_SET_TTYPE(hw_cent, TTYPE_XLATE_ONLY);
+			if (IMMU_ECAP_GET_PT(immu->immu_regs_excap))
+				CONT_SET_TTYPE(hw_cent, TTYPE_PASSTHRU);
+			else
+				/*LINTED*/
+				CONT_SET_TTYPE(hw_cent, TTYPE_XLATE_ONLY);
 			CONT_SET_AVAIL(hw_cent, IMMU_CONT_UNINITED);
 			CONT_SET_P(hw_cent);
 		}
@@ -3057,6 +3069,11 @@
 	mutex_enter(&immu_domain_lock);
 	domain = list_head(&immu_unity_domain_list);
 	for (; domain; domain = list_next(&immu_unity_domain_list, domain)) {
+		/*
+		 * Nothing to do if the IOMMU supports passthrough.
+		 */
+		if (IMMU_ECAP_GET_PT(domain->dom_immu->immu_regs_excap))
+			continue;
 
 		/* There is no vmem_arena for unity domains. Just map it */
 		ddi_err(DER_LOG, NULL, "IMMU: unity-domain: Adding map "