Module Name:    src
Committed By:   matt
Date:           Mon Jul  9 17:23:37 UTC 2012

Modified Files:
        src/sys/arch/mips/include [matt-nb5-mips64]: cpu.h pmap.h
        src/sys/arch/mips/mips [matt-nb5-mips64]: pmap.c pmap_segtab.c
            pmap_tlb.c

Log Message:
Use a spinlock to protect the segtab queues.  Use union pmap_segmap and
pmap_segmap_t to track -HEAD.  Use KERNEL_PID for the same reason.


To generate a diff of this commit:
cvs rdiff -u -r1.90.16.44 -r1.90.16.45 src/sys/arch/mips/include/cpu.h
cvs rdiff -u -r1.54.26.25 -r1.54.26.26 src/sys/arch/mips/include/pmap.h
cvs rdiff -u -r1.179.16.44 -r1.179.16.45 src/sys/arch/mips/mips/pmap.c
cvs rdiff -u -r1.1.2.16 -r1.1.2.17 src/sys/arch/mips/mips/pmap_segtab.c
cvs rdiff -u -r1.1.2.23 -r1.1.2.24 src/sys/arch/mips/mips/pmap_tlb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/include/cpu.h
diff -u src/sys/arch/mips/include/cpu.h:1.90.16.44 src/sys/arch/mips/include/cpu.h:1.90.16.45
--- src/sys/arch/mips/include/cpu.h:1.90.16.44	Mon Feb 27 17:04:39 2012
+++ src/sys/arch/mips/include/cpu.h	Mon Jul  9 17:23:37 2012
@@ -120,9 +120,9 @@ struct cpu_info {
 	int ci_tlb_slot;		/* reserved tlb entry for cpu_info */
 	u_int ci_pmap_asid_cur;		/* current ASID */
 	struct pmap_tlb_info *ci_tlb_info; /* tlb information for this cpu */
-	union segtab *ci_pmap_seg0tab;
+	union pmap_segtab *ci_pmap_seg0tab;
 #ifdef _LP64
-	union segtab *ci_pmap_segtab;
+	union pmap_segtab *ci_pmap_segtab;
 #else
 	vaddr_t ci_pmap_srcbase;	/* starting VA of ephemeral src space */
 	vaddr_t ci_pmap_dstbase;	/* starting VA of ephemeral dst space */

Index: src/sys/arch/mips/include/pmap.h
diff -u src/sys/arch/mips/include/pmap.h:1.54.26.25 src/sys/arch/mips/include/pmap.h:1.54.26.26
--- src/sys/arch/mips/include/pmap.h:1.54.26.25	Mon Feb 27 16:57:05 2012
+++ src/sys/arch/mips/include/pmap.h	Mon Jul  9 17:23:37 2012
@@ -104,6 +104,8 @@
  * dynamically allocated at boot time.
  */
 
+#define	KERNEL_PID		0
+
 #define mips_trunc_seg(x)	((vaddr_t)(x) & ~SEGOFSET)
 #define mips_round_seg(x)	(((vaddr_t)(x) + SEGOFSET) & ~SEGOFSET)
 
@@ -115,17 +117,15 @@
 
 union pt_entry;
 
-union segtab {
-#ifdef _LP64
-	union segtab	*seg_seg[PMAP_SEGTABSIZE];
-#endif
-	union pt_entry	*seg_tab[PMAP_SEGTABSIZE];
-};
+typedef union pmap_segtab {
+	union pmap_segtab *	seg_seg[PMAP_SEGTABSIZE];
+	union pt_entry	*	seg_tab[PMAP_SEGTABSIZE];
+} pmap_segtab_t;
 #else
 /*
  * Modules don't need to know this.
  */
-union segtab;
+typedef union pmap_segtab pmap_segtab_t;
 #endif
 
 /*
@@ -155,6 +155,7 @@ void pmap_pte_process(struct pmap *, vad
 void pmap_segtab_activate(struct pmap *, struct lwp *);
 void pmap_segtab_init(struct pmap *);
 void pmap_segtab_destroy(struct pmap *, pte_callback_t, uintptr_t);
+extern kmutex_t pmap_segtab_lock;
 #endif /* _KERNEL */
 
 /*
@@ -182,7 +183,7 @@ typedef struct pmap {
 	volatile uint32_t	pm_onproc;	/* pmap is active on ... */
 	volatile uint32_t	pm_shootdown_pending;
 #endif
-	union segtab		*pm_segtab;	/* pointers to pages of PTEs */
+	pmap_segtab_t *		pm_segtab;	/* pointers to pages of PTEs */
 	u_int			pm_count;	/* pmap reference count */
 	u_int			pm_flags;
 #define	PMAP_DEFERRED_ACTIVATE	0x0001
@@ -304,8 +305,10 @@ struct vm_page *mips_pmap_alloc_poolpage
 #define	POOL_VTOPHYS(va)	(MIPS_KSEG0_P(va) \
 				    ? MIPS_KSEG0_TO_PHYS(va) \
 				    : MIPS_XKPHYS_TO_PHYS(va))
+#define	POOL_PHYSTOV(pa)	MIPS_PHYS_TO_XKPHYS_CACHED((paddr_t)(pa))
 #else
 #define	POOL_VTOPHYS(va)	MIPS_KSEG0_TO_PHYS((vaddr_t)(va))
+#define	POOL_PHYSTOV(pa)	MIPS_PHYS_TO_KSEG0((paddr_t)(pa))
 #endif
 
 /*

Index: src/sys/arch/mips/mips/pmap.c
diff -u src/sys/arch/mips/mips/pmap.c:1.179.16.44 src/sys/arch/mips/mips/pmap.c:1.179.16.45
--- src/sys/arch/mips/mips/pmap.c:1.179.16.44	Mon Feb 27 16:57:06 2012
+++ src/sys/arch/mips/mips/pmap.c	Mon Jul  9 17:23:37 2012
@@ -760,6 +760,11 @@ pmap_init(void)
 #endif
 
 	/*
+	 * Initialize the segtab lock.
+	 */
+	mutex_init(&pmap_segtab_lock, MUTEX_DEFAULT, IPL_HIGH);      
+
+	/*
 	 * Set a low water mark on the pv_entry pool, so that we are
 	 * more likely to have these around even in extreme memory
 	 * starvation.

Index: src/sys/arch/mips/mips/pmap_segtab.c
diff -u src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.16 src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.17
--- src/sys/arch/mips/mips/pmap_segtab.c:1.1.2.16	Thu Jul  5 17:28:39 2012
+++ src/sys/arch/mips/mips/pmap_segtab.c	Mon Jul  9 17:23:37 2012
@@ -119,13 +119,8 @@ __KERNEL_RCSID(0, "pmap_segtab.c,v 1.1.2
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
-#include <sys/pool.h>
 #include <sys/mutex.h>
 #include <sys/atomic.h>
-#ifdef SYSVSHM
-#include <sys/shm.h>
-#endif
-#include <sys/socketvar.h>	/* XXX: for sock_loan_thresh */
 
 #include <uvm/uvm.h>
 
@@ -134,25 +129,29 @@ __KERNEL_RCSID(0, "pmap_segtab.c,v 1.1.2
 #include <mips/locore.h>
 #include <mips/pte.h>
 
-CTASSERT(NBPG >= sizeof(union segtab));
+CTASSERT(NBPG >= sizeof(pmap_segtab_t));
+#define PMAP_PTP_CACHE
 
-union segtab * volatile free_segtab;		/* free list kept locally */
+struct pmap_segtab_info {
+	pmap_segtab_t *free_segtab;	/* free list kept locally */
 #ifdef DEBUG
-uint32_t nget_segtab;
-uint32_t nput_segtab;
-uint32_t npage_segtab;
-#define	SEGTAB_ADD(n, v)	(n ## _segtab += (v))
+	uint32_t nget_segtab;
+	uint32_t nput_segtab;
+	uint32_t npage_segtab;
+#define	SEGTAB_ADD(n, v)	(pmap_segtab_info.n ## _segtab += (v))
 #else
 #define	SEGTAB_ADD(n, v)	((void) 0)
 #endif
-
-/*
- * Keep a list of idle page tables.
- */
-#define PMAP_PTP_CACHE
 #ifdef PMAP_PTP_CACHE
-static struct pgflist ptp_pgflist = LIST_HEAD_INITIALIZER(ptp_pgflist);
+	struct pgflist ptp_pgflist;	/* Keep a list of idle page tables. */
 #endif
+} pmap_segtab_info = {
+#ifdef PMAP_PTP_CACHE
+	.ptp_pgflist = LIST_HEAD_INITIALIZER(pmap_segtab_info.ptp_pgflist),
+#endif
+};
+
+kmutex_t pmap_segtab_lock;
 
 static inline struct vm_page *
 pmap_pte_pagealloc(void)
@@ -171,17 +170,17 @@ pmap_pte_pagealloc(void)
 	return pg;
 }
 
-static inline pt_entry_t * 
+static inline pt_entry_t *
 pmap_segmap(struct pmap *pmap, vaddr_t va)
 {
-	union segtab *stp = pmap->pm_segtab;
+	pmap_segtab_t *stp = pmap->pm_segtab;
 	KASSERT(!mm_md_direct_mapped_virt(va, NULL, NULL));
 #ifdef _LP64
 	stp = stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)];
 	if (stp == NULL)
 		return NULL;
 #endif
-	
+
 	return stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)];
 }
 
@@ -196,28 +195,26 @@ pmap_pte_lookup(pmap_t pmap, vaddr_t va)
 }
 
 static void
-pmap_segtab_free(union segtab *stp)
+pmap_segtab_free(pmap_segtab_t *stp)
 {
 	/*
 	 * Insert the the segtab into the segtab freelist.
 	 */
-	for (;;) {
-		void *tmp = free_segtab;
-		stp->seg_tab[0] = tmp;
-		if (tmp == atomic_cas_ptr(&free_segtab, tmp, stp)) {
-			SEGTAB_ADD(nput, 1);
-			break;
-		}
-	}
+	mutex_spin_enter(&pmap_segtab_lock);
+	stp->seg_seg[0] = pmap_segtab_info.free_segtab;
+	pmap_segtab_info.free_segtab = stp;
+	SEGTAB_ADD(nput, 1);
+	mutex_spin_exit(&pmap_segtab_lock);
 }
 
 static void
-pmap_segtab_release(pmap_t pmap, union segtab **stp_p, bool free_stp,
+pmap_segtab_release(pmap_t pmap, pmap_segtab_t **stp_p, bool free_stp,
 	pte_callback_t callback, uintptr_t flags,
 	vaddr_t va, vsize_t vinc)
 {
-	union segtab *stp = *stp_p;
+	pmap_segtab_t *stp = *stp_p;
 
+	KASSERT(((va / vinc) & (PMAP_SEGTABSIZE - 1)) == 0);
 	for (size_t i = 0; i < PMAP_SEGTABSIZE; i++, va += vinc) {
 #ifdef _LP64
 		if (vinc > NBSEG) {
@@ -241,12 +238,12 @@ pmap_segtab_release(pmap_t pmap, union s
 		 */
 		if (callback != NULL) {
 			(*callback)(pmap, va, va + vinc, pte, flags);
-		} 
+		}
 #ifdef DEBUG
 		for (size_t j = 0; j < NPTEPG; j++) {
 			if (pte[j].pt_entry)
 				panic("%s: pte entry %p not 0 (%#x)",
-				   __func__, &pte[j], pte[j].pt_entry);
+				    __func__, &pte[j], pte[j].pt_entry);
 		}
 #endif
 
@@ -262,12 +259,12 @@ pmap_segtab_release(pmap_t pmap, union s
 		if (MIPS_CACHE_VIRTUAL_ALIAS)
 			mips_dcache_inv_range((vaddr_t)pte, PAGE_SIZE);
 #endif	/* MIPS3_PLUS */
-		paddr_t pa = mips_pmap_unmap_poolpage((vaddr_t)pte);
+		paddr_t pa = PMAP_UNMAP_POOLPAGE((vaddr_t)pte);
 		struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
 #ifdef PMAP_PTP_CACHE
-		mutex_spin_enter(&uvm_fpageqlock);
-		LIST_INSERT_HEAD(&ptp_pgflist, pg, listq.list);
-		mutex_spin_exit(&uvm_fpageqlock);
+		mutex_spin_enter(&pmap_segtab_lock);
+		LIST_INSERT_HEAD(&pmap_segtab_info.ptp_pgflist, pg, listq.list);
+		mutex_spin_exit(&pmap_segtab_lock);
 #else
 		uvm_km_pagefree(pg);
 #endif
@@ -293,25 +290,21 @@ pmap_segtab_release(pmap_t pmap, union s
  *	the map will be used in software only, and
  *	is bounded by that size.
  */
-static union segtab *
+static pmap_segtab_t *
 pmap_segtab_alloc(void)
 {
-	union segtab *stp;
+	pmap_segtab_t *stp;
+
  again:
-	stp = NULL;
-	while (__predict_true(free_segtab != NULL)) {
-		union segtab *next_stp;
-		stp = free_segtab;
-		next_stp = (union segtab *)stp->seg_tab[0];
-		if (stp == atomic_cas_ptr(&free_segtab, stp, next_stp)) {
-			SEGTAB_ADD(nget, 1);
-			break;
-		}
+	mutex_spin_enter(&pmap_segtab_lock);
+	if (__predict_true((stp = pmap_segtab_info.free_segtab) != NULL)) {
+		pmap_segtab_info.free_segtab = stp->seg_seg[0];
+		stp->seg_seg[0] = NULL;
+		SEGTAB_ADD(nget, 1);
 	}
-	
-	if (__predict_true(stp != NULL)) {
-		stp->seg_tab[0] = NULL;
-	} else {
+	mutex_spin_exit(&pmap_segtab_lock);
+
+	if (__predict_false(stp == NULL)) {
 		struct vm_page * const stp_pg = pmap_pte_pagealloc();
 
 		if (__predict_false(stp_pg == NULL)) {
@@ -327,25 +320,23 @@ pmap_segtab_alloc(void)
 #ifdef _LP64
 		KASSERT(mips_options.mips3_xkphys_cached);
 #endif
-		stp = (union segtab *)mips_pmap_map_poolpage(stp_pa);
-		const size_t n = NBPG / sizeof(union segtab);
+		stp = (pmap_segtab_t *)PMAP_MAP_POOLPAGE(stp_pa);
+		const size_t n = NBPG / sizeof(*stp);
 		if (n > 1) {
 			/*
 			 * link all the segtabs in this page together
 			 */
 			for (size_t i = 1; i < n - 1; i++) {
-				stp[i].seg_tab[0] = (void *)&stp[i+1];
+				stp[i].seg_seg[0] = &stp[i+1];
 			}
 			/*
 			 * Now link the new segtabs into the free segtab list.
 			 */
-			for (;;) {
-				void *tmp = free_segtab;
-				stp[n-1].seg_tab[0] = tmp;
-				if (tmp == atomic_cas_ptr(&free_segtab, tmp, stp+1))
-					break;
-			}
+			mutex_spin_enter(&pmap_segtab_lock);
+			stp[n-1].seg_seg[0] = pmap_segtab_info.free_segtab;
+			pmap_segtab_info.free_segtab = stp + 1;
 			SEGTAB_ADD(nput, n - 1);
+			mutex_spin_exit(&pmap_segtab_lock);
 		}
 	}
 
@@ -380,12 +371,12 @@ pmap_segtab_destroy(pmap_t pmap, pte_cal
 		return;
 
 #ifdef _LP64
-	pmap_segtab_release(pmap, &pmap->pm_segtab,
-	    func == NULL, func, flags, 0, NBXSEG);
+	const vsize_t vinc = NBXSEG;
 #else
-	pmap_segtab_release(pmap, &pmap->pm_segtab,
-	    func == NULL, func, flags, 0, NBSEG);
+	const vsize_t vinc = NBSEG;
 #endif
+	pmap_segtab_release(pmap, &pmap->pm_segtab,
+	    func == NULL, func, flags, 0, vinc);
 }
 
 /*
@@ -455,18 +446,18 @@ pmap_pte_process(pmap_t pmap, vaddr_t sv
 pt_entry_t *
 pmap_pte_reserve(pmap_t pmap, vaddr_t va, int flags)
 {
-	union segtab *stp = pmap->pm_segtab;
+	pmap_segtab_t *stp = pmap->pm_segtab;
 	pt_entry_t *pte;
 
 	pte = pmap_pte_lookup(pmap, va);
 	if (__predict_false(pte == NULL)) {
 #ifdef _LP64
-		union segtab ** const stp_p =
+		pmap_segtab_t ** const stp_p =
 		    &stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)];
 		if (__predict_false((stp = *stp_p) == NULL)) {
-			union segtab *nstp = pmap_segtab_alloc();
+			pmap_segtab_t *nstp = pmap_segtab_alloc();
 #ifdef MULTIPROCESSOR
-			union segtab *ostp = atomic_cas_ptr(stp_p, NULL, nstp);
+			pmap_segtab_t *ostp = atomic_cas_ptr(stp_p, NULL, nstp);
 			if (__predict_false(ostp != NULL)) {
 				pmap_segtab_free(nstp);
 				nstp = ostp;
@@ -479,13 +470,13 @@ pmap_pte_reserve(pmap_t pmap, vaddr_t va
 		KASSERT(stp == pmap->pm_segtab->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)]);
 #endif /* _LP64 */
 		struct vm_page *pg = NULL;
-#if defined(PMAP_PTP_CACHE)
-		mutex_spin_enter(&uvm_fpageqlock);
-		if ((pg = LIST_FIRST(&ptp_pgflist)) != NULL) {
+#ifdef PMAP_PTP_CACHE
+		mutex_spin_enter(&pmap_segtab_lock);
+		if ((pg = LIST_FIRST(&pmap_segtab_info.ptp_pgflist)) != NULL) {
 			LIST_REMOVE(pg, listq.list);
-			KASSERT(LIST_FIRST(&ptp_pgflist) != pg);
+			KASSERT(LIST_FIRST(&pmap_segtab_info.ptp_pgflist) != pg);
 		}
-		mutex_spin_exit(&uvm_fpageqlock);
+		mutex_spin_exit(&pmap_segtab_lock);
 #endif
 		if (pg == NULL)
 			pg = pmap_pte_pagealloc();
@@ -511,9 +502,10 @@ pmap_pte_reserve(pmap_t pmap, vaddr_t va
 		 */
 		if (__predict_false(opte != NULL)) {
 #ifdef PMAP_PTP_CACHE
-			mutex_spin_enter(&uvm_fpageqlock);
-			LIST_INSERT_HEAD(&ptp_pgflist, pg, listq.list);
-			mutex_spin_exit(&uvm_fpageqlock);
+			mutex_spin_enter(&pmap_segtab_lock);
+			LIST_INSERT_HEAD(&pmap_segtab_info.ptp_pgflist,
+			    pg, listq.list);
+			mutex_spin_exit(&pmap_segtab_lock);
 #else
 			uvm_km_pagefree(pg);
 #endif

Index: src/sys/arch/mips/mips/pmap_tlb.c
diff -u src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.23 src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.24
--- src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.23	Thu Feb 16 23:02:22 2012
+++ src/sys/arch/mips/mips/pmap_tlb.c	Mon Jul  9 17:23:37 2012
@@ -191,7 +191,7 @@ pmap_pai_reset(struct pmap_tlb_info *ti,
 	/*
 	 * We must have an ASID but it must not be onproc (on a processor).
 	 */
-	KASSERT(pai->pai_asid);
+	KASSERT(pai->pai_asid > KERNEL_PID);
 #ifdef MULTIPROCESSOR
 	KASSERT((pm->pm_onproc & ti->ti_cpu_mask) == 0);
 #endif
@@ -412,7 +412,7 @@ pmap_tlb_asid_reinitialize(struct pmap_t
 	for (pai = LIST_FIRST(&ti->ti_pais); pai != NULL; pai = next) {
 		struct pmap * const pm = PAI_PMAP(pai, ti);
 		next = LIST_NEXT(pai, pai_link);
-		KASSERT(pai->pai_asid != 0);
+		KASSERT(pai->pai_asid > KERNEL_PID);
 #ifdef MULTIPROCESSOR
 		if (pm->pm_onproc & ti->ti_cpu_mask) {
 			if (!TLBINFO_ASID_INUSE_P(ti, pai->pai_asid)) {
@@ -470,7 +470,7 @@ pmap_tlb_shootdown_process(void)
 			 * The victim is an active pmap so we will just
 			 * invalidate its TLB entries.
 			 */
-			KASSERT(pai->pai_asid != 0);
+			KASSERT(pai->pai_asid > KERNEL_PID);
 			pmap_tlb_asid_check();
 			tlb_invalidate_asids(pai->pai_asid, pai->pai_asid + 1);
 			pmap_tlb_asid_check();
@@ -568,7 +568,7 @@ pmap_tlb_target_bystander(struct pmap_tl
 		ti->ti_tlbinvop = TLBINV_KERNEL_MAP(ti->ti_tlbinvop);
 		ti->ti_victim = NULL;
 	} else {
-		KASSERT(pai->pai_asid);
+		KASSERT(pai->pai_asid > KERNEL_PID);
 		if (__predict_false(ti->ti_victim == pm)) {
 			KASSERT(ti->ti_tlbinvop == TLBINV_ONE);
 			/*

Reply via email to