Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 11 Dec 2011 17:19:49 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228412 - in head/sys/powerpc: aim include
Message-ID:  <201112111719.pBBHJn48061450@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sun Dec 11 17:19:48 2011
New Revision: 228412
URL: http://svn.freebsd.org/changeset/base/228412

Log:
  Keep track of PVO entries in each pmap, which allows much faster
  pmap_remove() for large sparse requests. This can prevent pmap_remove()
  operations on 64-bit process destruction or swapout that would take
  several hundred times the lifetime of the universe to complete. This
  behavior is largely indistinguishable from a hang.

Modified:
  head/sys/powerpc/aim/mmu_oea.c
  head/sys/powerpc/aim/mmu_oea64.c
  head/sys/powerpc/include/pmap.h

Modified: head/sys/powerpc/aim/mmu_oea.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea.c	Sun Dec 11 17:10:33 2011	(r228411)
+++ head/sys/powerpc/aim/mmu_oea.c	Sun Dec 11 17:19:48 2011	(r228412)
@@ -824,6 +824,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t k
 	for (i = 0; i < 16; i++)
 		kernel_pmap->pm_sr[i] = EMPTY_SEGMENT + i;
 	CPU_FILL(&kernel_pmap->pm_active);
+	LIST_INIT(&kernel_pmap->pmap_pvo);
 
 	/*
 	 * Set up the Open Firmware mappings
@@ -1582,6 +1583,7 @@ moea_pinit(mmu_t mmu, pmap_t pmap)
 
 	KASSERT((int)pmap < VM_MIN_KERNEL_ADDRESS, ("moea_pinit: virt pmap"));
 	PMAP_LOCK_INIT(pmap);
+	LIST_INIT(&pmap->pmap_pvo);
 
 	entropy = 0;
 	__asm __volatile("mftb %0" : "=r"(entropy));
@@ -1765,10 +1767,17 @@ moea_remove(mmu_t mmu, pmap_t pm, vm_off
 
 	vm_page_lock_queues();
 	PMAP_LOCK(pm);
-	for (; sva < eva; sva += PAGE_SIZE) {
-		pvo = moea_pvo_find_va(pm, sva, &pteidx);
-		if (pvo != NULL) {
-			moea_pvo_remove(pvo, pteidx);
+	if ((eva - sva)/PAGE_SIZE < 10) {
+		for (; sva < eva; sva += PAGE_SIZE) {
+			pvo = moea_pvo_find_va(pm, sva, &pteidx);
+			if (pvo != NULL)
+				moea_pvo_remove(pvo, pteidx);
+		}
+	} else {
+		LIST_FOREACH(pvo, &pm->pmap_pvo, pvo_plink) {
+			if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva)
+				continue;
+			moea_pvo_remove(pvo, -1);
 		}
 	}
 	PMAP_UNLOCK(pm);
@@ -1931,6 +1940,11 @@ moea_pvo_enter(pmap_t pm, uma_zone_t zon
 	moea_pte_create(&pvo->pvo_pte.pte, sr, va, pa | pte_lo);
 
 	/*
+	 * Add to pmap list
+	 */
+	LIST_INSERT_HEAD(&pm->pmap_pvo, pvo, pvo_plink);
+
+	/*
 	 * Remember if the list was empty and therefore will be the first
 	 * item.
 	 */
@@ -1996,9 +2010,10 @@ moea_pvo_remove(struct pvo_entry *pvo, i
 	}
 
 	/*
-	 * Remove this PVO from the PV list.
+	 * Remove this PVO from the PV and pmap lists.
 	 */
 	LIST_REMOVE(pvo, pvo_vlink);
+	LIST_REMOVE(pvo, pvo_plink);
 
 	/*
 	 * Remove this from the overflow list and return it to the pool

Modified: head/sys/powerpc/aim/mmu_oea64.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea64.c	Sun Dec 11 17:10:33 2011	(r228411)
+++ head/sys/powerpc/aim/mmu_oea64.c	Sun Dec 11 17:19:48 2011	(r228412)
@@ -831,6 +831,7 @@ moea64_mid_bootstrap(mmu_t mmup, vm_offs
 
 	kernel_pmap->pmap_phys = kernel_pmap;
 	CPU_FILL(&kernel_pmap->pm_active);
+	LIST_INIT(&kernel_pmap->pmap_pvo);
 
 	PMAP_LOCK_INIT(kernel_pmap);
 
@@ -1855,6 +1856,7 @@ void
 moea64_pinit(mmu_t mmu, pmap_t pmap)
 {
 	PMAP_LOCK_INIT(pmap);
+	LIST_INIT(&pmap->pmap_pvo);
 
 	pmap->pm_slb_tree_root = slb_alloc_tree();
 	pmap->pm_slb = slb_alloc_user_cache();
@@ -1868,6 +1870,7 @@ moea64_pinit(mmu_t mmu, pmap_t pmap)
 	uint32_t hash;
 
 	PMAP_LOCK_INIT(pmap);
+	LIST_INIT(&pmap->pmap_pvo);
 
 	if (pmap_bootstrapped)
 		pmap->pmap_phys = (pmap_t)moea64_kextract(mmu,
@@ -2034,10 +2037,18 @@ moea64_remove(mmu_t mmu, pmap_t pm, vm_o
 
 	vm_page_lock_queues();
 	PMAP_LOCK(pm);
-	for (; sva < eva; sva += PAGE_SIZE) {
-		pvo = moea64_pvo_find_va(pm, sva);
-		if (pvo != NULL)
+	if ((eva - sva)/PAGE_SIZE < 10) {
+		for (; sva < eva; sva += PAGE_SIZE) {
+			pvo = moea64_pvo_find_va(pm, sva);
+			if (pvo != NULL)
+				moea64_pvo_remove(mmu, pvo);
+		}
+	} else {
+		LIST_FOREACH(pvo, &pm->pmap_pvo, pvo_plink) {
+			if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva)
+				continue;
 			moea64_pvo_remove(mmu, pvo);
+		}
 	}
 	vm_page_unlock_queues();
 	PMAP_UNLOCK(pm);
@@ -2231,6 +2242,11 @@ moea64_pvo_enter(mmu_t mmu, pmap_t pm, u
 	    (uint64_t)(pa) | pte_lo, flags);
 
 	/*
+	 * Add to pmap list
+	 */
+	LIST_INSERT_HEAD(&pm->pmap_pvo, pvo, pvo_plink);
+
+	/*
 	 * Remember if the list was empty and therefore will be the first
 	 * item.
 	 */
@@ -2311,9 +2327,10 @@ moea64_pvo_remove(mmu_t mmu, struct pvo_
 	}
 
 	/*
-	 * Remove this PVO from the PV list.
+	 * Remove this PVO from the PV and pmap lists.
 	 */
 	LIST_REMOVE(pvo, pvo_vlink);
+	LIST_REMOVE(pvo, pvo_plink);
 
 	/*
 	 * Remove this from the overflow list and return it to the pool

Modified: head/sys/powerpc/include/pmap.h
==============================================================================
--- head/sys/powerpc/include/pmap.h	Sun Dec 11 17:10:33 2011	(r228411)
+++ head/sys/powerpc/include/pmap.h	Sun Dec 11 17:19:48 2011	(r228412)
@@ -88,28 +88,13 @@ struct pmap_md {
 #endif /* !defined(NPMAPS) */
 
 struct	slbtnode;
-
-struct	pmap {
-	struct	mtx	pm_mtx;
-	
-    #ifdef __powerpc64__
-	struct slbtnode	*pm_slb_tree_root;
-	struct slb	**pm_slb;
-	int		pm_slb_len;
-    #else
-	register_t	pm_sr[16];
-    #endif
-	cpuset_t	pm_active;
-
-	struct pmap	*pmap_phys;
-	struct		pmap_statistics	pm_stats;
-};
-
+struct	pmap;
 typedef	struct pmap *pmap_t;
 
 struct pvo_entry {
 	LIST_ENTRY(pvo_entry) pvo_vlink;	/* Link to common virt page */
 	LIST_ENTRY(pvo_entry) pvo_olink;	/* Link to overflow entry */
+	LIST_ENTRY(pvo_entry) pvo_plink;	/* Link to pmap entries */
 	union {
 		struct	pte pte;		/* 32 bit PTE */
 		struct	lpte lpte;		/* 64 bit PTE */
@@ -137,6 +122,23 @@ LIST_HEAD(pvo_head, pvo_entry);
 	((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID))
 #define	PVO_VSID(pvo)		((pvo)->pvo_vpn >> 16)
 
+struct	pmap {
+	struct	mtx	pm_mtx;
+	
+    #ifdef __powerpc64__
+	struct slbtnode	*pm_slb_tree_root;
+	struct slb	**pm_slb;
+	int		pm_slb_len;
+    #else
+	register_t	pm_sr[16];
+    #endif
+	cpuset_t	pm_active;
+
+	struct pmap	*pmap_phys;
+	struct		pmap_statistics	pm_stats;
+	struct pvo_head pmap_pvo;
+};
+
 struct	md_page {
 	u_int64_t	 mdpg_attrs;
 	vm_memattr_t	 mdpg_cache_attrs;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112111719.pBBHJn48061450>