Mercurial > illumos > illumos-gate
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 "