changeset 12619:60877912fc2d

6789139 px_mmu_detach destroys a vmem arena before its address-space allocations are free'd
author andrew.rutz@sun.com
date Mon, 14 Jun 2010 07:12:23 -0700
parents 0e5eaf4bf546
children 12fcd99a642d
files usr/src/uts/sun4/io/px/px_lib.h usr/src/uts/sun4/io/px/px_mmu.c usr/src/uts/sun4u/io/px/px_hlib.c usr/src/uts/sun4u/io/px/px_lib4u.c usr/src/uts/sun4u/io/px/px_lib4u.h usr/src/uts/sun4v/io/px/px_lib4v.c
diffstat 6 files changed, 112 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sun4/io/px/px_lib.h	Mon Jun 14 02:22:19 2010 -0700
+++ b/usr/src/uts/sun4/io/px/px_lib.h	Mon Jun 14 07:12:23 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef	_SYS_PX_LIB_H
@@ -91,6 +90,7 @@
     uint64_t *lo_p, uint64_t *hi_p);
 extern int px_lib_iommu_getbypass(dev_info_t *dip, r_addr_t ra,
     io_attributes_t attr, io_addr_t *io_addr_p);
+extern int px_lib_iommu_detach(px_t *px_p);
 extern uint64_t px_lib_ro_bypass(dev_info_t *dip, io_attributes_t attr,
     uint64_t io_addr);
 extern int px_lib_dma_sync(dev_info_t *dip, dev_info_t *rdip,
--- a/usr/src/uts/sun4/io/px/px_mmu.c	Mon Jun 14 02:22:19 2010 -0700
+++ b/usr/src/uts/sun4/io/px/px_mmu.c	Mon Jun 14 07:12:23 2010 -0700
@@ -19,12 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * PX mmu initialization and configuration
  */
@@ -153,6 +150,8 @@
 {
 	px_mmu_t *mmu_p = px_p->px_mmu_p;
 
+	(void) px_lib_iommu_detach(px_p);
+
 	/*
 	 * Free the dvma resource map.
 	 */
--- a/usr/src/uts/sun4u/io/px/px_hlib.c	Mon Jun 14 02:22:19 2010 -0700
+++ b/usr/src/uts/sun4u/io/px/px_hlib.c	Mon Jun 14 07:12:23 2010 -0700
@@ -18,9 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -1697,7 +1697,7 @@
 void
 hvio_mmu_init(caddr_t csr_base, pxu_t *pxu_p)
 {
-	uint64_t	val, i, obp_tsb_pa, *base_tte_addr;
+	uint64_t	val, i, obp_tsb_pa;
 	uint_t obp_tsb_entries;
 
 	bzero(pxu_p->tsb_vaddr, pxu_p->tsb_size);
@@ -1709,17 +1709,12 @@
 
 	obp_tsb_entries = mmu_tsb_entries(csr_base, pxu_p);
 
-	base_tte_addr = pxu_p->tsb_vaddr +
-	    ((pxu_p->tsb_size >> 3) - obp_tsb_entries);
-
-	for (i = 0; i < obp_tsb_entries; i++) {
-		uint64_t tte = lddphys(obp_tsb_pa + i * 8);
-
-		if (!MMU_TTE_VALID(tte))
-			continue;
-
-		base_tte_addr[i] = tte;
-	}
+	/* save "shape" of OBP's TSB for use during Detach */
+	pxu_p->obp_tsb_paddr = obp_tsb_pa;
+	pxu_p->obp_tsb_entries = obp_tsb_entries;
+
+	/* For each Valid TTE in OBP's TSB, save its value in px's IOTSB */
+	hvio_obptsb_attach(pxu_p);
 
 	/*
 	 * Invalidate the TLB through the diagnostic register.
@@ -1906,6 +1901,80 @@
 	return (ret);
 }
 
+/*
+ * Copy each Valid OBP TTE from OBP's IOTSB to px's IOTSB.
+ */
+void
+hvio_obptsb_attach(pxu_t *pxu_p)
+{
+	uint64_t	obp_tsb_pa;
+	uint64_t	*base_tte_addr;
+	uint64_t	i;
+	uint_t		obp_tsb_entries;
+
+	obp_tsb_pa = pxu_p->obp_tsb_paddr;
+	obp_tsb_entries = pxu_p->obp_tsb_entries;
+
+	/*
+	 * Compute the starting addr of the area reserved for
+	 * OBP's TTEs; OBP's TTEs are stored at the highest addrs
+	 * of px's IOTSB.
+	 */
+	base_tte_addr = pxu_p->tsb_vaddr +
+	    ((pxu_p->tsb_size >> 3) - obp_tsb_entries);
+
+	for (i = 0; i < obp_tsb_entries; i++) {
+		uint64_t tte = lddphys(obp_tsb_pa + i * 8);
+
+		if (!MMU_TTE_VALID(tte))
+			continue;
+
+		base_tte_addr[i] = tte;
+	}
+}
+
+/*
+ * For each Valid OBP TTE, deallocate space from the vmem Arena used
+ * to manage the TTE's associated DVMA addr space.  (Allocation from
+ * the DVMA Arena was done in px_mmu_attach).
+ */
+void
+hvio_obptsb_detach(px_t *px_p)
+{
+	uint64_t	obp_tsb_pa;
+	uint64_t	i;
+	uint_t		obp_tsb_entries;
+	uint_t		obp_tsb_bias;
+	px_mmu_t	*mmu_p = px_p->px_mmu_p;
+	vmem_t		*dvma_map;
+	pxu_t		*pxu_p = (pxu_t *)px_p->px_plat_p;
+
+	dvma_map = mmu_p->mmu_dvma_map;
+
+	obp_tsb_pa = pxu_p->obp_tsb_paddr;
+	obp_tsb_entries = pxu_p->obp_tsb_entries;
+	/*
+	 * OBP's TTEs are located at the high end of px's IOTSB.
+	 * Equivalently, OBP's DVMA space is allocated at the high end
+	 * of px's DVMA space.  Compute the bias that references
+	 * OBP's first possible page of DVMA space.
+	 */
+	obp_tsb_bias = (pxu_p->tsb_size >> 3) - obp_tsb_entries;
+
+	for (i = 0; i < obp_tsb_entries; i++) {
+		caddr_t va;
+		uint64_t tte = lddphys(obp_tsb_pa + i * 8);
+
+		if (!MMU_TTE_VALID(tte))
+			continue;
+
+		/* deallocate the TTE's associated page of DVMA space */
+		va = (caddr_t)(MMU_PTOB(mmu_p->dvma_base_pg + obp_tsb_bias +
+		    i));
+		vmem_xfree(dvma_map, va, MMU_PAGE_SIZE);
+	}
+}
+
 /* ARGSUSED */
 uint64_t
 hvio_get_bypass_base(pxu_t *pxu_p)
--- a/usr/src/uts/sun4u/io/px/px_lib4u.c	Mon Jun 14 02:22:19 2010 -0700
+++ b/usr/src/uts/sun4u/io/px/px_lib4u.c	Mon Jun 14 07:12:23 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -574,6 +573,17 @@
 	return (DDI_SUCCESS);
 }
 
+int
+px_lib_iommu_detach(px_t *px_p)
+{
+	/*
+	 * Deallocate DVMA addr space that was reserved for OBP TTE's
+	 * during Attach.
+	 */
+	hvio_obptsb_detach(px_p);
+
+	return (DDI_SUCCESS);
+}
 
 /*
  * Checks dma attributes against system bypass ranges
--- a/usr/src/uts/sun4u/io/px/px_lib4u.h	Mon Jun 14 02:22:19 2010 -0700
+++ b/usr/src/uts/sun4u/io/px/px_lib4u.h	Mon Jun 14 07:12:23 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _SYS_PX_LIB4U_H
@@ -111,6 +110,8 @@
 	/* sun4u specific vars */
 	caddr_t			px_address[4];
 	ddi_acc_handle_t	px_ac[4];
+	uint64_t		obp_tsb_paddr;
+	uint_t			obp_tsb_entries;
 
 	/* PCItool */
 	caddr_t		pcitool_addr;
@@ -328,6 +329,8 @@
 extern uint64_t hvio_get_bypass_base(pxu_t *pxu_p);
 extern uint64_t hvio_get_bypass_end(pxu_t *pxu_p);
 extern uint64_t px_get_range_prop(px_t *px_p, pci_ranges_t *rp, int bank);
+extern void hvio_obptsb_attach(pxu_t *pxu_p);
+extern void hvio_obptsb_detach(px_t *px_p);
 
 
 /*
--- a/usr/src/uts/sun4v/io/px/px_lib4v.c	Mon Jun 14 02:22:19 2010 -0700
+++ b/usr/src/uts/sun4v/io/px/px_lib4v.c	Mon Jun 14 07:12:23 2010 -0700
@@ -555,6 +555,13 @@
 }
 
 /*ARGSUSED*/
+int
+px_lib_iommu_detach(px_t *px_p)
+{
+	return (DDI_SUCCESS);
+}
+
+/*ARGSUSED*/
 uint64_t
 px_get_rng_parent_hi_mask(px_t *px_p)
 {