svn commit: r254926 - in projects/random_number_generator: . share/man/man5 share/man/man9 share/misc sys/arm/arm sys/arm/include sys/dev/amdtemp sys/dev/xen/netback sys/vm tools/build/mk tools/bui...

Mark Murray markm at FreeBSD.org
Mon Aug 26 18:21:06 UTC 2013


Author: markm
Date: Mon Aug 26 18:21:04 2013
New Revision: 254926
URL: http://svnweb.freebsd.org/changeset/base/254926

Log:
  MFC

Added:
  projects/random_number_generator/tools/build/options/WITHOUT_ICONV
     - copied unchanged from r254924, head/tools/build/options/WITHOUT_ICONV
  projects/random_number_generator/tools/build/options/WITH_LIBICONV_COMPAT
     - copied unchanged from r254924, head/tools/build/options/WITH_LIBICONV_COMPAT
  projects/random_number_generator/tools/build/options/WITH_USB_GADGET_EXAMPLES
     - copied unchanged from r254924, head/tools/build/options/WITH_USB_GADGET_EXAMPLES
Deleted:
  projects/random_number_generator/tools/build/options/WITH_ICONV
Modified:
  projects/random_number_generator/ObsoleteFiles.inc
  projects/random_number_generator/share/man/man5/src.conf.5
  projects/random_number_generator/share/man/man9/Makefile
  projects/random_number_generator/share/misc/committers-src.dot
  projects/random_number_generator/sys/arm/arm/pmap-v6.c
  projects/random_number_generator/sys/arm/include/param.h
  projects/random_number_generator/sys/arm/include/pmap.h
  projects/random_number_generator/sys/arm/include/pte.h
  projects/random_number_generator/sys/arm/include/vmparam.h
  projects/random_number_generator/sys/dev/amdtemp/amdtemp.c
  projects/random_number_generator/sys/dev/xen/netback/netback.c
  projects/random_number_generator/sys/vm/vm_page.c
  projects/random_number_generator/tools/build/mk/OptionalObsoleteFiles.inc
  projects/random_number_generator/usr.bin/kdump/kdump.c
  projects/random_number_generator/usr.bin/kdump/mksubr
  projects/random_number_generator/usr.sbin/mfiutil/mfi_drive.c
  projects/random_number_generator/usr.sbin/mfiutil/mfiutil.8
  projects/random_number_generator/usr.sbin/mfiutil/mfiutil.c
Directory Properties:
  projects/random_number_generator/   (props changed)
  projects/random_number_generator/sys/   (props changed)

Modified: projects/random_number_generator/ObsoleteFiles.inc
==============================================================================
--- projects/random_number_generator/ObsoleteFiles.inc	Mon Aug 26 18:16:05 2013	(r254925)
+++ projects/random_number_generator/ObsoleteFiles.inc	Mon Aug 26 18:21:04 2013	(r254926)
@@ -38,6 +38,14 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20130822: bind 9.9.3-P2 import
+OLD_LIBS+=usr/lib/liblwres.so.80
+# 20130814: vm_page_busy(9)
+OLD_FILES+=usr/share/man/man9/vm_page_flash.9.gz
+OLD_FILES+=usr/share/man/man9/vm_page_io.9.gz
+OLD_FILES+=usr/share/man/man9/vm_page_io_finish.9.gz
+OLD_FILES+=usr/share/man/man9/vm_page_io_start.9.gz
+OLD_FILES+=usr/share/man/man9/vm_page_wakeup.9.gz
 # 20130710: libkvm version bump 
 OLD_LIBS+=lib/libkvm.so.5
 OLD_LIBS+=usr/lib32/libkvm.so.5
@@ -114,6 +122,7 @@ OLD_FILES+=usr/include/clang/3.2/xmmintr
 OLD_FILES+=usr/include/clang/3.2/xopintrin.h
 OLD_DIRS+=usr/include/clang/3.2
 # 20130404: legacy ATA stack removed
+OLD_FILES+=etc/periodic/daily/405.status-ata-raid
 OLD_FILES+=rescue/atacontrol
 OLD_FILES+=sbin/atacontrol
 OLD_FILES+=usr/share/man/man8/atacontrol.8.gz

Modified: projects/random_number_generator/share/man/man5/src.conf.5
==============================================================================
--- projects/random_number_generator/share/man/man5/src.conf.5	Mon Aug 26 18:16:05 2013	(r254925)
+++ projects/random_number_generator/share/man/man5/src.conf.5	Mon Aug 26 18:21:04 2013	(r254926)
@@ -1,7 +1,7 @@
 .\" DO NOT EDIT-- this file is automatically generated.
 .\" from FreeBSD: head/tools/build/options/makeman 253304 2013-07-12 23:08:44Z bapt
 .\" $FreeBSD$
-.Dd July 16, 2013
+.Dd August 26, 2013
 .Dt SRC.CONF 5
 .Os
 .Sh NAME
@@ -245,9 +245,6 @@ Set to not build the BSD licensed versio
 .It Va WITH_BSD_GREP
 .\" from FreeBSD: head/tools/build/options/WITH_BSD_GREP 222273 2011-05-25 01:04:12Z obrien
 Install BSD-licensed grep as '[ef]grep' instead of GNU grep.
-.It Va WITH_BSD_PATCH
-.\" from FreeBSD: head/tools/build/options/WITH_BSD_PATCH 246074 2013-01-29 17:03:18Z gabor
-Install BSD-licensed patch as 'patch' instead of GNU patch.
 .It Va WITHOUT_BSNMP
 .\" from FreeBSD: head/tools/build/options/WITHOUT_BSNMP 183306 2008-09-23 16:15:42Z sam
 Set to not build or install
@@ -506,6 +503,9 @@ When set, it also enforces the following
 .It
 .Va WITHOUT_GNU_SUPPORT
 .El
+.It Va WITH_GNU_PATCH
+.\" from FreeBSD: head/tools/build/options/WITH_GNU_PATCH 253689 2013-07-26 21:25:18Z pfg
+Install GNU-licensed patch as 'patch' instead of BSD patch.
 .It Va WITHOUT_GNU_SUPPORT
 .\" from FreeBSD: head/tools/build/options/WITHOUT_GNU_SUPPORT 156932 2006-03-21 07:50:50Z ru
 Set to build some programs without optional GNU support.
@@ -538,9 +538,15 @@ Set to build Hesiod support.
 .It Va WITHOUT_HTML
 .\" from FreeBSD: head/tools/build/options/WITHOUT_HTML 156932 2006-03-21 07:50:50Z ru
 Set to not build HTML docs.
-.It Va WITH_ICONV
-.\" from FreeBSD: head/tools/build/options/WITH_ICONV 219020 2011-02-25 00:10:26Z gabor
-Set to build iconv as part of libc.
+.It Va WITHOUT_ICONV
+.\" from FreeBSD: head/tools/build/options/WITHOUT_ICONV 254919 2013-08-26 17:15:56Z antoine
+Set to not build iconv as part of libc.
+When set, it also enforces the following options:
+.Pp
+.Bl -item -compact
+.It
+.Va WITHOUT_LIBICONV_COMPAT
+.El
 .It Va WITHOUT_INET
 .\" from FreeBSD: head/tools/build/options/WITHOUT_INET 221266 2011-04-30 17:58:28Z bz
 Set to not build programs and libraries related to IPv4 networking.
@@ -701,6 +707,9 @@ runtime linker.
 .It Va WITHOUT_LIBCPLUSPLUS
 .\" from FreeBSD: head/tools/build/options/WITHOUT_LIBCPLUSPLUS 246262 2013-02-02 22:42:46Z dim
 Set to avoid building libcxxrt and libc++.
+.It Va WITH_LIBICONV_COMPAT
+.\" from FreeBSD: head/tools/build/options/WITH_LIBICONV_COMPAT 254919 2013-08-26 17:15:56Z antoine
+Set to build libiconv API and link time compatibility.
 .It Va WITHOUT_LIBPTHREAD
 .\" from FreeBSD: head/tools/build/options/WITHOUT_LIBPTHREAD 188848 2009-02-20 11:09:55Z mtm
 Set to not build the
@@ -1129,6 +1138,9 @@ When set, it also enforces the following
 .It Va WITHOUT_USB
 .\" from FreeBSD: head/tools/build/options/WITHOUT_USB 156932 2006-03-21 07:50:50Z ru
 Set to not build USB-related programs and libraries.
+.It Va WITH_USB_GADGET_EXAMPLES
+.\" from FreeBSD: head/tools/build/options/WITH_USB_GADGET_EXAMPLES 254919 2013-08-26 17:15:56Z antoine
+Set to build USB gadget kernel modules.
 .It Va WITHOUT_UTMPX
 .\" from FreeBSD: head/tools/build/options/WITHOUT_UTMPX 231530 2012-02-11 20:28:42Z ed
 Set to not build user accounting tools such as

Modified: projects/random_number_generator/share/man/man9/Makefile
==============================================================================
--- projects/random_number_generator/share/man/man9/Makefile	Mon Aug 26 18:16:05 2013	(r254925)
+++ projects/random_number_generator/share/man/man9/Makefile	Mon Aug 26 18:21:04 2013	(r254926)
@@ -324,6 +324,7 @@ MAN=	accept_filter.9 \
 	vm_map_wire.9 \
 	vm_page_alloc.9 \
 	vm_page_bits.9 \
+	vm_page_busy.9 \
 	vm_page_cache.9 \
 	vm_page_deactivate.9 \
 	vm_page_dontneed.9 \

Modified: projects/random_number_generator/share/misc/committers-src.dot
==============================================================================
--- projects/random_number_generator/share/misc/committers-src.dot	Mon Aug 26 18:16:05 2013	(r254925)
+++ projects/random_number_generator/share/misc/committers-src.dot	Mon Aug 26 18:21:04 2013	(r254926)
@@ -187,6 +187,7 @@ jkim [label="Jung-uk Kim\njkim at FreeBSD.o
 jkoshy [label="A. Joseph Koshy\njkoshy at FreeBSD.org\n1998/05/13"]
 jlh [label="Jeremie Le Hen\njlh at FreeBSD.org\n2012/04/22"]
 jls [label="Jordan Sissel\njls at FreeBSD.org\n2006/12/06"]
+jmg [label="John-Mark Gurney\njmg at FreeBSD.org\n1997/02/13"]
 joerg [label="Joerg Wunsch\njoerg at FreeBSD.org\n1993/11/14"]
 jon [label="Jonathan Chen\njon at FreeBSD.org\n2000/10/17"]
 jonathan [label="Jonathan Anderson\njonathan at FreeBSD.org\n2010/10/07"]
@@ -495,6 +496,7 @@ jlemon -> brooks
 
 joerg -> brian
 joerg -> eik
+joerg -> jmg
 joerg -> le
 joerg -> netchild
 joerg -> schweikh

Modified: projects/random_number_generator/sys/arm/arm/pmap-v6.c
==============================================================================
--- projects/random_number_generator/sys/arm/arm/pmap-v6.c	Mon Aug 26 18:16:05 2013	(r254925)
+++ projects/random_number_generator/sys/arm/arm/pmap-v6.c	Mon Aug 26 18:21:04 2013	(r254926)
@@ -171,6 +171,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 #include <vm/vm_pageout.h>
 #include <vm/vm_extern.h>
+#include <vm/vm_reserv.h>
 
 #include <machine/md_var.h>
 #include <machine/cpu.h>
@@ -201,6 +202,8 @@ int pmap_debug_level = 0;
 #define PV_STAT(x)	do { } while (0)
 #endif
 
+#define	pa_to_pvh(pa)	(&pv_table[pa_index(pa)])
+
 #ifdef ARM_L2_PIPT
 #define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((pa), (size))
 #define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((pa), (size))
@@ -215,10 +218,16 @@ extern struct pv_addr systempage;
  * Internal function prototypes
  */
 
+static PMAP_INLINE
+struct pv_entry		*pmap_find_pv(struct md_page *, pmap_t, vm_offset_t);
 static void		pmap_free_pv_chunk(struct pv_chunk *pc);
 static void		pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv);
 static pv_entry_t 	pmap_get_pv_entry(pmap_t pmap, boolean_t try);
 static vm_page_t 	pmap_pv_reclaim(pmap_t locked_pmap);
+static boolean_t	pmap_pv_insert_section(pmap_t, vm_offset_t,
+    vm_paddr_t);
+static struct pv_entry	*pmap_remove_pv(struct vm_page *, pmap_t, vm_offset_t);
+static int		pmap_pvh_wired_mappings(struct md_page *, int);
 
 static void		pmap_enter_locked(pmap_t, vm_offset_t, vm_prot_t,
     vm_page_t, vm_prot_t, boolean_t, int);
@@ -226,6 +235,14 @@ static vm_paddr_t	pmap_extract_locked(pm
 static void		pmap_alloc_l1(pmap_t);
 static void		pmap_free_l1(pmap_t);
 
+static void		pmap_map_section(pmap_t, vm_offset_t, vm_offset_t,
+    vm_prot_t, boolean_t);
+static void		pmap_promote_section(pmap_t, vm_offset_t);
+static boolean_t	pmap_demote_section(pmap_t, vm_offset_t);
+static boolean_t	pmap_enter_section(pmap_t, vm_offset_t, vm_page_t,
+    vm_prot_t);
+static void		pmap_remove_section(pmap_t, vm_offset_t);
+
 static int		pmap_clearbit(struct vm_page *, u_int);
 
 static struct l2_bucket *pmap_get_l2_bucket(pmap_t, vm_offset_t);
@@ -403,6 +420,7 @@ int	pmap_needs_pte_sync;
  */
 static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
 static int pv_entry_count, pv_entry_max, pv_entry_high_water;
+static struct md_page *pv_table;
 static int shpgperproc = PMAP_SHPGPERPROC;
 
 struct pv_chunk *pv_chunkbase;		/* KVA block for pv_chunks */
@@ -433,6 +451,11 @@ static const uint32_t pc_freemask[_NPCM]
 
 static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
 
+/* Superpages utilization enabled = 1 / disabled = 0 */
+static int sp_enabled = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN, &sp_enabled, 0,
+    "Are large page mappings enabled?");
+
 SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
     "Current number of pv entries");
 
@@ -891,7 +914,9 @@ static int
 pmap_clearbit(struct vm_page *m, u_int maskbits)
 {
 	struct l2_bucket *l2b;
-	struct pv_entry *pv;
+	struct pv_entry *pv, *pve, *next_pv;
+	struct md_page *pvh;
+	pd_entry_t *pl1pd;
 	pt_entry_t *ptep, npte, opte;
 	pmap_t pmap;
 	vm_offset_t va;
@@ -899,7 +924,79 @@ pmap_clearbit(struct vm_page *m, u_int m
 	int count = 0;
 
 	rw_wlock(&pvh_global_lock);
+	if ((m->flags & PG_FICTITIOUS) != 0)
+		goto small_mappings;
 
+	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
+		va = pv->pv_va;
+		pmap = PV_PMAP(pv);
+		PMAP_LOCK(pmap);
+		pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+		KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO,
+		    ("pmap_clearbit: valid section mapping expected"));
+		if ((maskbits & PVF_WRITE) && (pv->pv_flags & PVF_WRITE))
+			(void)pmap_demote_section(pmap, va);
+		else if ((maskbits & PVF_REF) && L1_S_REFERENCED(*pl1pd)) {
+			if (pmap_demote_section(pmap, va)) {
+				if ((pv->pv_flags & PVF_WIRED) == 0) {
+					/*
+					 * Remove the mapping to a single page
+					 * so that a subsequent access may
+					 * repromote. Since the underlying
+					 * l2_bucket is fully populated, this
+					 * removal never frees an entire
+					 * l2_bucket.
+					 */
+					va += (VM_PAGE_TO_PHYS(m) &
+					    L1_S_OFFSET);
+					l2b = pmap_get_l2_bucket(pmap, va);
+					KASSERT(l2b != NULL,
+					    ("pmap_clearbit: no l2 bucket for "
+					     "va 0x%#x, pmap 0x%p", va, pmap));
+					ptep = &l2b->l2b_kva[l2pte_index(va)];
+					*ptep = 0;
+					PTE_SYNC(ptep);
+					pmap_free_l2_bucket(pmap, l2b, 1);
+					pve = pmap_remove_pv(m, pmap, va);
+					KASSERT(pve != NULL, ("pmap_clearbit: "
+					    "no PV entry for managed mapping"));
+					pmap_free_pv_entry(pmap, pve);
+
+				}
+			}
+		} else if ((maskbits & PVF_MOD) && L1_S_WRITABLE(*pl1pd)) {
+			if (pmap_demote_section(pmap, va)) {
+				if ((pv->pv_flags & PVF_WIRED) == 0) {
+					/*
+					 * Write protect the mapping to a
+					 * single page so that a subsequent
+					 * write access may repromote.
+					 */
+					va += (VM_PAGE_TO_PHYS(m) &
+					    L1_S_OFFSET);
+					l2b = pmap_get_l2_bucket(pmap, va);
+					KASSERT(l2b != NULL,
+					    ("pmap_clearbit: no l2 bucket for "
+					     "va 0x%#x, pmap 0x%p", va, pmap));
+					ptep = &l2b->l2b_kva[l2pte_index(va)];
+					if ((*ptep & L2_S_PROTO) != 0) {
+						pve = pmap_find_pv(&m->md,
+						    pmap, va);
+						KASSERT(pve != NULL,
+						    ("pmap_clearbit: no PV "
+						    "entry for managed mapping"));
+						pve->pv_flags &= ~PVF_WRITE;
+						*ptep &= ~L2_APX;
+						PTE_SYNC(ptep);
+					}
+				}
+			}
+		}
+		PMAP_UNLOCK(pmap);
+	}
+
+small_mappings:
 	if (TAILQ_EMPTY(&m->md.pv_list)) {
 		rw_wunlock(&pvh_global_lock);
 		return (0);
@@ -917,6 +1014,8 @@ pmap_clearbit(struct vm_page *m, u_int m
 		PMAP_LOCK(pmap);
 
 		l2b = pmap_get_l2_bucket(pmap, va);
+		KASSERT(l2b != NULL, ("pmap_clearbit: no l2 bucket for "
+		    "va 0x%#x, pmap 0x%p", va, pmap));
 
 		ptep = &l2b->l2b_kva[l2pte_index(va)];
 		npte = opte = *ptep;
@@ -999,14 +1098,15 @@ pmap_enter_pv(struct vm_page *m, struct 
  * => caller should hold lock on vm_page
  */
 static PMAP_INLINE struct pv_entry *
-pmap_find_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va)
+pmap_find_pv(struct md_page *md, pmap_t pmap, vm_offset_t va)
 {
 	struct pv_entry *pv;
 
 	rw_assert(&pvh_global_lock, RA_WLOCKED);
-	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list)
-	    if (pmap == PV_PMAP(pv) && va == pv->pv_va)
-		    break;
+	TAILQ_FOREACH(pv, &md->pv_list, pv_list)
+		if (pmap == PV_PMAP(pv) && va == pv->pv_va)
+			break;
+
 	return (pv);
 }
 
@@ -1075,7 +1175,7 @@ pmap_remove_pv(struct vm_page *m, pmap_t
 	rw_assert(&pvh_global_lock, RA_WLOCKED);
 	PMAP_ASSERT_LOCKED(pmap);
 
-	pve = pmap_find_pv(m, pmap, va);	/* find corresponding pve */
+	pve = pmap_find_pv(&m->md, pmap, va);	/* find corresponding pve */
 	if (pve != NULL) {
 		TAILQ_REMOVE(&m->md.pv_list, pve, pv_list);
 		if (pve->pv_flags & PVF_WIRED)
@@ -1106,7 +1206,7 @@ pmap_modify_pv(struct vm_page *m, pmap_t
 
 	PMAP_ASSERT_LOCKED(pmap);
 	rw_assert(&pvh_global_lock, RA_WLOCKED);
-	if ((npv = pmap_find_pv(m, pmap, va)) == NULL)
+	if ((npv = pmap_find_pv(&m->md, pmap, va)) == NULL)
 		return (0);
 
 	/*
@@ -1143,6 +1243,7 @@ pmap_pinit0(struct pmap *pmap)
 	bcopy(kernel_pmap, pmap, sizeof(*pmap));
 	bzero(&pmap->pm_mtx, sizeof(pmap->pm_mtx));
 	PMAP_LOCK_INIT(pmap);
+	TAILQ_INIT(&pmap->pm_pvchunk);
 }
 
 /*
@@ -1206,6 +1307,8 @@ pmap_ptelist_init(vm_offset_t *head, voi
 void
 pmap_init(void)
 {
+	vm_size_t s;
+	int i, pv_npg;
 
 	PDEBUG(1, printf("pmap_init: phys_start = %08x\n", PHYSADDR));
 
@@ -1215,6 +1318,32 @@ pmap_init(void)
 	    NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
 
 	/*
+	 * Are large page mappings supported and enabled?
+	 */
+	TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled);
+	if (sp_enabled) {
+		KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0,
+		    ("pmap_init: can't assign to pagesizes[1]"));
+		pagesizes[1] = NBPDR;
+	}
+
+	/*
+	 * Calculate the size of the pv head table for superpages.
+	 */
+	for (i = 0; phys_avail[i + 1]; i += 2);
+	pv_npg = round_1mpage(phys_avail[(i - 2) + 1]) / NBPDR;
+
+	/*
+	 * Allocate memory for the pv head table for superpages.
+	 */
+	s = (vm_size_t)(pv_npg * sizeof(struct md_page));
+	s = round_page(s);
+	pv_table = (struct md_page *)kmem_malloc(kernel_arena, s,
+	    M_WAITOK | M_ZERO);
+	for (i = 0; i < pv_npg; i++)
+		TAILQ_INIT(&pv_table[i].pv_list);
+
+	/*
 	 * Initialize the address space for the pv chunks.
 	 */
 
@@ -1243,6 +1372,25 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_
 SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
 	"Page share factor per proc");
 
+static SYSCTL_NODE(_vm_pmap, OID_AUTO, section, CTLFLAG_RD, 0,
+    "1MB page mapping counters");
+
+static u_long pmap_section_demotions;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, demotions, CTLFLAG_RD,
+    &pmap_section_demotions, 0, "1MB page demotions");
+
+static u_long pmap_section_mappings;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, mappings, CTLFLAG_RD,
+    &pmap_section_mappings, 0, "1MB page mappings");
+
+static u_long pmap_section_p_failures;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, p_failures, CTLFLAG_RD,
+    &pmap_section_p_failures, 0, "1MB page promotion failures");
+
+static u_long pmap_section_promotions;
+SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, promotions, CTLFLAG_RD,
+    &pmap_section_promotions, 0, "1MB page promotions");
+
 int
 pmap_fault_fixup(pmap_t pmap, vm_offset_t va, vm_prot_t ftype, int user)
 {
@@ -1257,7 +1405,47 @@ pmap_fault_fixup(pmap_t pmap, vm_offset_
 	l1idx = L1_IDX(va);
 	rw_wlock(&pvh_global_lock);
 	PMAP_LOCK(pmap);
-
+	/*
+	 * Check and possibly fix-up L1 section mapping
+	 * only when superpage mappings are enabled to speed up.
+	 */
+	if (sp_enabled) {
+		pl1pd = &pmap->pm_l1->l1_kva[l1idx];
+		l1pd = *pl1pd;
+		if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+			/* Catch an access to the vectors section */
+			if (l1idx == L1_IDX(vector_page))
+				goto out;
+			/*
+			 * Stay away from the kernel mappings.
+			 * None of them should fault from L1 entry.
+			 */
+			if (pmap == pmap_kernel())
+				goto out;
+			/*
+			 * Catch a forbidden userland access
+			 */
+			if (user && !(l1pd & L1_S_PROT_U))
+				goto out;
+			/*
+			 * Superpage is always either mapped read only
+			 * or it is modified and permitted to be written
+			 * by default. Therefore, process only reference
+			 * flag fault and demote page in case of write fault.
+			 */
+			if ((ftype & VM_PROT_WRITE) && !L1_S_WRITABLE(l1pd) &&
+			    L1_S_REFERENCED(l1pd)) {
+				(void)pmap_demote_section(pmap, va);
+				goto out;
+			} else if (!L1_S_REFERENCED(l1pd)) {
+				/* Mark the page "referenced" */
+				*pl1pd = l1pd | L1_S_REF;
+				PTE_SYNC(pl1pd);
+				goto l1_section_out;
+			} else
+				goto out;
+		}
+	}
 	/*
 	 * If there is no l2_dtable for this address, then the process
 	 * has no business accessing it.
@@ -1310,7 +1498,7 @@ pmap_fault_fixup(pmap_t pmap, vm_offset_
 		}
 		/* Get the current flags for this page. */
 
-		pv = pmap_find_pv(m, pmap, va);
+		pv = pmap_find_pv(&m->md, pmap, va);
 		if (pv == NULL) {
 			goto out;
 		}
@@ -1345,7 +1533,7 @@ pmap_fault_fixup(pmap_t pmap, vm_offset_
 		if ((m = PHYS_TO_VM_PAGE(pa)) == NULL)
 			goto out;
 		/* Get the current flags for this page. */
-		pv = pmap_find_pv(m, pmap, va);
+		pv = pmap_find_pv(&m->md, pmap, va);
 		if (pv == NULL)
 			goto out;
 
@@ -1410,6 +1598,7 @@ pmap_fault_fixup(pmap_t pmap, vm_offset_
 	}
 #endif
 
+l1_section_out:
 	cpu_tlb_flushID_SE(va);
 	cpu_cpwait();
 
@@ -1976,6 +2165,24 @@ pmap_growkernel(vm_offset_t addr)
 	kernel_vm_end = pmap_curmaxkvaddr;
 }
 
+/*
+ * Returns TRUE if the given page is mapped individually or as part of
+ * a 1MB section.  Otherwise, returns FALSE.
+ */
+boolean_t
+pmap_page_is_mapped(vm_page_t m)
+{
+	boolean_t rv;
+
+	if ((m->oflags & VPO_UNMANAGED) != 0)
+		return (FALSE);
+	rw_wlock(&pvh_global_lock);
+	rv = !TAILQ_EMPTY(&m->md.pv_list) ||
+	    ((m->flags & PG_FICTITIOUS) == 0 &&
+	    !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
 
 /*
  * Remove all pages from specified address space
@@ -1990,9 +2197,12 @@ pmap_remove_pages(pmap_t pmap)
 {
 	struct pv_entry *pv;
  	struct l2_bucket *l2b = NULL;
- 	vm_page_t m;
- 	pt_entry_t *ptep;
 	struct pv_chunk *pc, *npc;
+	struct md_page *pvh;
+	pd_entry_t *pl1pd, l1pd;
+ 	pt_entry_t *ptep;
+ 	vm_page_t m, mt;
+	vm_offset_t va;
 	uint32_t inuse, bitmask;
 	int allfree, bit, field, idx;
  
@@ -2008,33 +2218,63 @@ pmap_remove_pages(pmap_t pmap)
 				bitmask = 1ul << bit;
 				idx = field * sizeof(inuse) * NBBY + bit;
 				pv = &pc->pc_pventry[idx];
+				va = pv->pv_va;
 				inuse &= ~bitmask;
 				if (pv->pv_flags & PVF_WIRED) {
 					/* Cannot remove wired pages now. */
 					allfree = 0;
 					continue;
 				}
-				l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
-				KASSERT(l2b != NULL,
-				    ("No L2 bucket in pmap_remove_pages"));
-				ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
-				m = PHYS_TO_VM_PAGE(*ptep & L2_ADDR_MASK);
-				KASSERT((vm_offset_t)m >= KERNBASE,
-				    ("Trying to access non-existent page "
-				     "va %x pte %x", pv->pv_va, *ptep));
-				*ptep = 0;
-				PTE_SYNC(ptep);
+				pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+				l1pd = *pl1pd;
+				l2b = pmap_get_l2_bucket(pmap, va);
+				if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+					pvh = pa_to_pvh(l1pd & L1_S_FRAME);
+					TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+					if (TAILQ_EMPTY(&pvh->pv_list)) {
+						m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
+						KASSERT((vm_offset_t)m >= KERNBASE,
+						    ("Trying to access non-existent page "
+						     "va %x l1pd %x", trunc_1mpage(va), l1pd));
+						for (mt = m; mt < &m[L2_PTE_NUM_TOTAL]; mt++) {
+							if (TAILQ_EMPTY(&mt->md.pv_list))
+								vm_page_aflag_clear(mt, PGA_WRITEABLE);
+						}
+					}
+					if (l2b != NULL) {
+						KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL,
+						    ("pmap_remove_pages: l2_bucket occupancy error"));
+						pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL);
+					}
+					pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL;
+					*pl1pd = 0;
+					PTE_SYNC(pl1pd);
+				} else {
+					KASSERT(l2b != NULL,
+					    ("No L2 bucket in pmap_remove_pages"));
+					ptep = &l2b->l2b_kva[l2pte_index(va)];
+					m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
+					KASSERT((vm_offset_t)m >= KERNBASE,
+					    ("Trying to access non-existent page "
+					     "va %x pte %x", va, *ptep));
+					TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+					if (TAILQ_EMPTY(&m->md.pv_list) &&
+					    (m->flags & PG_FICTITIOUS) == 0) {
+						pvh = pa_to_pvh(l2pte_pa(*ptep));
+						if (TAILQ_EMPTY(&pvh->pv_list))
+							vm_page_aflag_clear(m, PGA_WRITEABLE);
+					}
+					*ptep = 0;
+					PTE_SYNC(ptep);
+					pmap_free_l2_bucket(pmap, l2b, 1);
+					pmap->pm_stats.resident_count--;
+				}
 
 				/* Mark free */
 				PV_STAT(pv_entry_frees++);
 				PV_STAT(pv_entry_spare++);
 				pv_entry_count--;
-				pmap->pm_stats.resident_count--;
 				pc->pc_map[field] |= bitmask;
-				TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
-				if (TAILQ_EMPTY(&m->md.pv_list))
-					vm_page_aflag_clear(m, PGA_WRITEABLE);
-				pmap_free_l2_bucket(pmap, l2b, 1);
 			}
 		}
 		if (allfree) {
@@ -2063,7 +2303,8 @@ pmap_kenter_supersection(vm_offset_t va,
 {
 	pd_entry_t pd = L1_S_PROTO | L1_S_SUPERSEC | (pa & L1_SUP_FRAME) |
 	    (((pa >> 32) & 0xf) << 20) | L1_S_PROT(PTE_KERNEL,
-	    VM_PROT_READ|VM_PROT_WRITE) | L1_S_DOM(PMAP_DOMAIN_KERNEL);
+	    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) |
+	    L1_S_DOM(PMAP_DOMAIN_KERNEL);
 	struct l1_ttable *l1;
 	vm_offset_t va0, va_end;
 
@@ -2092,7 +2333,8 @@ void
 pmap_kenter_section(vm_offset_t va, vm_offset_t pa, int flags)
 {
 	pd_entry_t pd = L1_S_PROTO | pa | L1_S_PROT(PTE_KERNEL,
-	    VM_PROT_READ|VM_PROT_WRITE) | L1_S_DOM(PMAP_DOMAIN_KERNEL);
+	    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) | L1_S_REF |
+	    L1_S_DOM(PMAP_DOMAIN_KERNEL);
 	struct l1_ttable *l1;
 
 	KASSERT(((va | pa) & L1_S_OFFSET) == 0,
@@ -2327,9 +2569,11 @@ pmap_is_prefaultable(pmap_t pmap, vm_off
 
 	if (!pmap_get_pde_pte(pmap, addr, &pdep, &ptep))
 		return (FALSE);
-	KASSERT(ptep != NULL, ("Valid mapping but no pte ?"));
-	if (*ptep == 0)
-		return (TRUE);
+	KASSERT((pdep != NULL && (l1pte_section_p(*pdep) || ptep != NULL)),
+	    ("Valid mapping but no pte ?"));
+	if (*pdep != 0 && !l1pte_section_p(*pdep))
+		if (*ptep == 0)
+			return (TRUE);
 	return (FALSE);
 }
 
@@ -2398,6 +2642,7 @@ pmap_get_pde_pte(pmap_t pmap, vm_offset_
 void
 pmap_remove_all(vm_page_t m)
 {
+	struct md_page *pvh;
 	pv_entry_t pv;
 	pmap_t pmap;
 	pt_entry_t *ptep;
@@ -2406,12 +2651,23 @@ pmap_remove_all(vm_page_t m)
 	pmap_t curpmap;
 	u_int is_exec = 0;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
-
-	if (TAILQ_EMPTY(&m->md.pv_list))
-		return;
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	rw_wlock(&pvh_global_lock);
+	if ((m->flags & PG_FICTITIOUS) != 0)
+		goto small_mappings;
+	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+	while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) {
+		pmap = PV_PMAP(pv);
+		PMAP_LOCK(pmap);
+		pd_entry_t *pl1pd;
+		pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
+		KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO,
+		    ("pmap_remove_all: valid section mapping expected"));
+		(void)pmap_demote_section(pmap, pv->pv_va);
+		PMAP_UNLOCK(pmap);
+	}
+small_mappings:
 	curpmap = vmspace_pmap(curproc->p_vmspace);
 	while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
 		pmap = PV_PMAP(pv);
@@ -2513,6 +2769,9 @@ void
 pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
 {
 	struct l2_bucket *l2b;
+	struct md_page *pvh;
+	struct pv_entry *pve;
+	pd_entry_t *pl1pd, l1pd;
 	pt_entry_t *ptep, pte;
 	vm_offset_t next_bucket;
 	u_int is_exec, is_refd;
@@ -2544,9 +2803,47 @@ pmap_protect(pmap_t pmap, vm_offset_t sv
 
 	while (sva < eva) {
 		next_bucket = L2_NEXT_BUCKET(sva);
+		/*
+		 * Check for large page.
+		 */
+		pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
+		l1pd = *pl1pd;
+		if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+			KASSERT(pmap != pmap_kernel(),
+			    ("pmap_protect: trying to modify "
+			    "kernel section protections"));
+			/*
+			 * Are we protecting the entire large page? If not,
+			 * demote the mapping and fall through.
+			 */
+			if (sva + L1_S_SIZE == L2_NEXT_BUCKET(sva) &&
+			    eva >= L2_NEXT_BUCKET(sva)) {
+				l1pd &= ~(L1_S_PROT_MASK | L1_S_XN);
+				if (!(prot & VM_PROT_EXECUTE))
+					*pl1pd |= L1_S_XN;
+				/*
+				 * At this point we are always setting
+				 * write-protect bit.
+				 */
+				l1pd |= L1_S_APX;
+				/* All managed superpages are user pages. */
+				l1pd |= L1_S_PROT_U;
+				*pl1pd = l1pd;
+				PTE_SYNC(pl1pd);
+				pvh = pa_to_pvh(l1pd & L1_S_FRAME);
+				pve = pmap_find_pv(pvh, pmap,
+				    trunc_1mpage(sva));
+				pve->pv_flags &= ~PVF_WRITE;
+				sva = next_bucket;
+				continue;
+			} else if (!pmap_demote_section(pmap, sva)) {
+				/* The large page mapping was destroyed. */
+				sva = next_bucket;
+				continue;
+			}
+		}
 		if (next_bucket > eva)
 			next_bucket = eva;
-
 		l2b = pmap_get_l2_bucket(pmap, sva);
 		if (l2b == NULL) {
 			sva = next_bucket;
@@ -2632,6 +2929,7 @@ pmap_enter_locked(pmap_t pmap, vm_offset
 	struct l2_bucket *l2b = NULL;
 	struct vm_page *om;
 	struct pv_entry *pve = NULL;
+	pd_entry_t *pl1pd, l1pd;
 	pt_entry_t *ptep, npte, opte;
 	u_int nflags;
 	u_int is_exec, is_refd;
@@ -2650,6 +2948,10 @@ pmap_enter_locked(pmap_t pmap, vm_offset
 		pa = VM_PAGE_TO_PHYS(m);
 	}
 
+	pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+	if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
+		panic("pmap_enter_locked: attempt pmap_enter_on 1MB page");
+
 	user = 0;
 	/*
 	 * Make sure userland mappings get the right permissions
@@ -2824,9 +3126,6 @@ validate:
 				 * L1 entry to avoid taking another
 				 * page/domain fault.
 				 */
-				pd_entry_t *pl1pd, l1pd;
-
-				pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
 				l1pd = l2b->l2b_phys |
 				    L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
 				if (*pl1pd != l1pd) {
@@ -2844,6 +3143,14 @@ validate:
 
 	if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap))
 		cpu_icache_sync_range(va, PAGE_SIZE);
+	/*
+	 * If both the l2b_occupancy and the reservation are fully
+	 * populated, then attempt promotion.
+	 */
+	if ((l2b->l2b_occupancy == L2_PTE_NUM_TOTAL) &&
+	    sp_enabled && (m->flags & PG_FICTITIOUS) == 0 &&
+	    vm_reserv_level_iffullpop(m) == 0)
+		pmap_promote_section(pmap, va);
 }
 
 /*
@@ -2862,6 +3169,7 @@ void
 pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
     vm_page_t m_start, vm_prot_t prot)
 {
+	vm_offset_t va;
 	vm_page_t m;
 	vm_pindex_t diff, psize;
 	vm_prot_t access;
@@ -2874,8 +3182,15 @@ pmap_enter_object(pmap_t pmap, vm_offset
 	rw_wlock(&pvh_global_lock);
 	PMAP_LOCK(pmap);
 	while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
-		pmap_enter_locked(pmap, start + ptoa(diff), access, m, prot,
-		    FALSE, M_NOWAIT);
+		va = start + ptoa(diff);
+		if ((va & L1_S_OFFSET) == 0 && L2_NEXT_BUCKET(va) <= end &&
+		    (VM_PAGE_TO_PHYS(m) & L1_S_OFFSET) == 0 &&
+		    sp_enabled && vm_reserv_level_iffullpop(m) == 0 &&
+		    pmap_enter_section(pmap, va, m, prot))
+			m = &m[L1_S_SIZE / PAGE_SIZE - 1];
+		else
+			pmap_enter_locked(pmap, va, access, m, prot,
+			    FALSE, M_NOWAIT);
 		m = TAILQ_NEXT(m, listq);
 	}
 	PMAP_UNLOCK(pmap);
@@ -2915,11 +3230,32 @@ void
 pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
 {
 	struct l2_bucket *l2b;
+	struct md_page *pvh;
+	struct pv_entry *pve;
+	pd_entry_t *pl1pd, l1pd;
 	pt_entry_t *ptep, pte;
 	vm_page_t m;
 
 	rw_wlock(&pvh_global_lock);
 	PMAP_LOCK(pmap);
+	pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
+	l1pd = *pl1pd;
+	if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
+		m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
+		KASSERT((m != NULL) && ((m->oflags & VPO_UNMANAGED) == 0),
+		    ("pmap_change_wiring: unmanaged superpage should not "
+		     "be changed"));
+		KASSERT(pmap != pmap_kernel(),
+		    ("pmap_change_wiring: managed kernel superpage "
+		     "should not exist"));
+		pvh = pa_to_pvh(l1pd & L1_S_FRAME);
+		pve = pmap_find_pv(pvh, pmap, trunc_1mpage(va));
+		if (!wired != ((pve->pv_flags & PVF_WIRED) == 0)) {
+			if (!pmap_demote_section(pmap, va))
+				panic("pmap_change_wiring: demotion failed");
+		} else
+			goto out;
+	}
 	l2b = pmap_get_l2_bucket(pmap, va);
 	KASSERT(l2b, ("No l2b bucket in pmap_change_wiring"));
 	ptep = &l2b->l2b_kva[l2pte_index(va)];
@@ -2928,6 +3264,7 @@ pmap_change_wiring(pmap_t pmap, vm_offse
 	if (m != NULL)
 		pmap_modify_pv(m, pmap, va, PVF_WIRED,
 		    wired == TRUE ? PVF_WIRED : 0);
+out:
 	rw_wunlock(&pvh_global_lock);
 	PMAP_UNLOCK(pmap);
 }
@@ -3034,10 +3371,6 @@ pmap_extract_and_hold(pmap_t pmap, vm_of
 retry:
 	l1pd = pmap->pm_l1->l1_kva[l1idx];
 	if (l1pte_section_p(l1pd)) {
-		/*
-		 * These should only happen for pmap_kernel()
-		 */
-		KASSERT(pmap == pmap_kernel(), ("huh"));
 		/* XXX: what to do about the bits > 32 ? */
 		if (l1pd & L1_S_SUPERSEC)
 			pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
@@ -3122,6 +3455,520 @@ pmap_pinit(pmap_t pmap)
 
 
 /***************************************************
+ * Superpage management routines.
+ ***************************************************/
+
+static PMAP_INLINE struct pv_entry *
+pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+	pv_entry_t pv;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+	pv = pmap_find_pv(pvh, pmap, va);
+	if (pv != NULL)
+		TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+
+	return (pv);
+}
+
+static void
+pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+	pv_entry_t pv;
+
+	pv = pmap_pvh_remove(pvh, pmap, va);
+	KASSERT(pv != NULL, ("pmap_pvh_free: pv not found"));
+	pmap_free_pv_entry(pmap, pv);
+}
+
+static boolean_t
+pmap_pv_insert_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+	struct md_page *pvh;
+	pv_entry_t pv;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	if (pv_entry_count < pv_entry_high_water && 
+	    (pv = pmap_get_pv_entry(pmap, TRUE)) != NULL) {
+		pv->pv_va = va;
+		pvh = pa_to_pvh(pa);
+		TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
+		return (TRUE);
+	} else
+		return (FALSE);
+}
+
+/*
+ * Create the pv entries for each of the pages within a superpage.
+ */
+static void
+pmap_pv_demote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+	struct md_page *pvh;
+	pv_entry_t pve, pv;
+	vm_offset_t va_last;
+	vm_page_t m;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	KASSERT((pa & L1_S_OFFSET) == 0,
+	    ("pmap_pv_demote_section: pa is not 1mpage aligned"));
+
+	/*
+	 * Transfer the 1mpage's pv entry for this mapping to the first
+	 * page's pv list.
+	 */
+	pvh = pa_to_pvh(pa);
+	va = trunc_1mpage(va);
+	pv = pmap_pvh_remove(pvh, pmap, va);
+	KASSERT(pv != NULL, ("pmap_pv_demote_section: pv not found"));
+	m = PHYS_TO_VM_PAGE(pa);
+	TAILQ_INSERT_HEAD(&m->md.pv_list, pv, pv_list);
+	/* Instantiate the remaining pv entries. */
+	va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE;
+	do {
+		m++;
+		KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+		    ("pmap_pv_demote_section: page %p is not managed", m));
+		va += PAGE_SIZE;
+		pve = pmap_get_pv_entry(pmap, FALSE);
+		pmap_enter_pv(m, pve, pmap, va, pv->pv_flags);
+	} while (va < va_last);
+}
+
+static void
+pmap_pv_promote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+	struct md_page *pvh;
+	pv_entry_t pv;
+	vm_offset_t va_last;
+	vm_page_t m;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	KASSERT((pa & L1_S_OFFSET) == 0,
+	    ("pmap_pv_promote_section: pa is not 1mpage aligned"));
+
+	/*
+	 * Transfer the first page's pv entry for this mapping to the
+	 * 1mpage's pv list.  Aside from avoiding the cost of a call
+	 * to get_pv_entry(), a transfer avoids the possibility that
+	 * get_pv_entry() calls pmap_pv_reclaim() and that pmap_pv_reclaim()
+	 * removes one of the mappings that is being promoted.
+	 */
+	m = PHYS_TO_VM_PAGE(pa);
+	va = trunc_1mpage(va);
+	pv = pmap_pvh_remove(&m->md, pmap, va);
+	KASSERT(pv != NULL, ("pmap_pv_promote_section: pv not found"));
+	pvh = pa_to_pvh(pa);
+	TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
+	/* Free the remaining pv entries in the newly mapped section pages */
+	va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE;
+	do {
+		m++;
+		va += PAGE_SIZE;
+		/*
+		 * Don't care the flags, first pv contains sufficient
+		 * information for all of the pages so nothing is really lost.
+		 */
+		pmap_pvh_free(&m->md, pmap, va);
+	} while (va < va_last);
+}
+
+/*
+ * Tries to create a 1MB page mapping.  Returns TRUE if successful and
+ * FALSE otherwise.  Fails if (1) page is unmanageg, kernel pmap or vectors
+ * page, (2) a mapping already exists at the specified virtual address, or
+ * (3) a pv entry cannot be allocated without reclaiming another pv entry. 
+ */
+static boolean_t
+pmap_enter_section(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+	pd_entry_t *pl1pd;
+	vm_offset_t pa;
+	struct l2_bucket *l2b;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	PMAP_ASSERT_LOCKED(pmap);
+
+	/* Skip kernel, vectors page and unmanaged mappings */
+	if ((pmap == pmap_kernel()) || (L1_IDX(va) == L1_IDX(vector_page)) ||
+	    ((m->oflags & VPO_UNMANAGED) != 0)) {
+		CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
+		    " in pmap %p", va, pmap);
+		return (FALSE);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list