changeset 12532:e0c8045b31e0

6897709 BAD TRAP: unix:page_get_mnode_freelist 6898574 incorrect pagetable handling in i86pc/vm
author Joe Bonasera <joe.bonasera@oracle.com>
date Wed, 02 Jun 2010 09:26:54 -0700
parents 0cd962838fce
children a474309e6ba5
files usr/src/uts/i86pc/vm/hat_i86.c usr/src/uts/i86pc/vm/htable.c usr/src/uts/i86pc/vm/vm_machdep.c
diffstat 3 files changed, 17 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/i86pc/vm/hat_i86.c	Wed Jun 02 08:32:30 2010 -0400
+++ b/usr/src/uts/i86pc/vm/hat_i86.c	Wed Jun 02 09:26:54 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) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Copyright (c) 2010, Intel Corporation.
@@ -2200,22 +2199,7 @@
 			x86_hm_enter(pp);
 		}
 
-		/*
-		 * If freeing the address space, check that the PTE
-		 * hasn't changed, as the mappings are no longer in use by
-		 * any thread, invalidation is unnecessary.
-		 * If not freeing, do a full invalidate.
-		 *
-		 * On the hypervisor we must always remove mappings, as a
-		 * writable mapping left behind could cause a page table
-		 * allocation to fail.
-		 */
-#if !defined(__xpv)
-		if (hat->hat_flags & HAT_FREEING)
-			old_pte = x86pte_get(ht, entry);
-		else
-#endif
-			old_pte = x86pte_inval(ht, entry, old_pte, pte_ptr);
+		old_pte = x86pte_inval(ht, entry, old_pte, pte_ptr);
 
 		/*
 		 * If the page hadn't changed we've unmapped it and can proceed
@@ -3421,6 +3405,13 @@
 	level_t		level;
 
 	XPV_DISALLOW_MIGRATE();
+
+	/*
+	 * prevent recursion due to kmem_free()
+	 */
+	++curthread->t_hatdepth;
+	ASSERT(curthread->t_hatdepth < 16);
+
 #if defined(__amd64)
 	/*
 	 * clear the vpm ref.
@@ -3448,6 +3439,8 @@
 				 * If not part of a larger page, we're done.
 				 */
 				if (cur_pp->p_szc <= pg_szcd) {
+					ASSERT(curthread->t_hatdepth > 0);
+					--curthread->t_hatdepth;
 					XPV_ALLOW_MIGRATE();
 					return (0);
 				}
--- a/usr/src/uts/i86pc/vm/htable.c	Wed Jun 02 08:32:30 2010 -0400
+++ b/usr/src/uts/i86pc/vm/htable.c	Wed Jun 02 09:26:54 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -334,18 +333,17 @@
 	 * Get an exclusive lock, might have to wait for a kmem reader.
 	 */
 	if (!page_tryupgrade(pp)) {
+		u_offset_t off = pp->p_offset;
 		page_unlock(pp);
-		/*
-		 * RFE: we could change this to not loop forever
-		 * For now looping works - it's just like sfmmu.
-		 */
-		while (!page_lock(pp, SE_EXCL, (kmutex_t *)NULL, P_RECLAIM))
-			continue;
+		pp = page_lookup(&kvp, off, SE_EXCL);
+		if (pp == NULL)
+			panic("page not found");
 	}
 #ifdef __xpv
 	if (kpm_vbase && xen_kpm_page(pfn, PT_VALID | PT_WRITABLE) < 0)
 		panic("failure making kpm r/w pfn=0x%lx", pfn);
 #endif
+	page_hashout(pp, NULL);
 	page_free(pp, 1);
 	page_unresv(1);
 }
--- a/usr/src/uts/i86pc/vm/vm_machdep.c	Wed Jun 02 08:32:30 2010 -0400
+++ b/usr/src/uts/i86pc/vm/vm_machdep.c	Wed Jun 02 09:26:54 2010 -0700
@@ -3982,7 +3982,6 @@
 	    &tmpseg, (caddr_t)(ctr += MMU_PAGESIZE));	/* changing VA usage */
 	if (pp != NULL) {
 		page_io_unlock(pp);
-		page_hashout(pp, NULL);
 		page_downgrade(pp);
 	}
 	return (pp);