Module Name:    src
Committed By:   jdc
Date:           Sun Dec  8 10:12:39 UTC 2013

Modified Files:
        src/sys/arch/sparc/sparc: pmap.c

Log Message:
Use a double linked list with a static head to track MMU entries.
Code from martin@.
Tested on SUN4 (4/330), SUN4C (SS2), and SUN4M (Krups, 4/630).


To generate a diff of this commit:
cvs rdiff -u -r1.353 -r1.354 src/sys/arch/sparc/sparc/pmap.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/sparc/sparc/pmap.c
diff -u src/sys/arch/sparc/sparc/pmap.c:1.353 src/sys/arch/sparc/sparc/pmap.c:1.354
--- src/sys/arch/sparc/sparc/pmap.c:1.353	Mon Nov 25 02:59:14 2013
+++ src/sys/arch/sparc/sparc/pmap.c	Sun Dec  8 10:12:39 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.353 2013/11/25 02:59:14 christos Exp $ */
+/*	$NetBSD: pmap.c,v 1.354 2013/12/08 10:12:39 jdc Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.353 2013/11/25 02:59:14 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.354 2013/12/08 10:12:39 jdc Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -279,12 +279,12 @@ pvhead4m(u_int pte)
  * by flushing (and invalidating) a TLB entry when appropriate before
  * altering an in-memory page table entry.
  */
-struct mmuq;
 struct mmuentry {
-	TAILQ_ENTRY(mmuentry)	me_list;	/* usage list link */
+	struct {
+	    struct mmuentry *prev, *next;
+	}			me_list;	/* usage list link */
 	TAILQ_ENTRY(mmuentry)	me_pmchain;	/* pmap owner link */
 	struct	pmap *me_pmap;		/* pmap, if in use */
-	struct	mmuq *me_queue;		/* where do we live */
 	u_short	me_vreg;		/* associated virtual region/segment */
 	u_short	me_vseg;		/* associated virtual region/segment */
 	u_short	me_cookie;		/* hardware SMEG/PMEG number */
@@ -295,24 +295,54 @@ struct mmuentry {
 struct mmuentry *mmusegments;	/* allocated in pmap_bootstrap */
 struct mmuentry *mmuregions;	/* allocated in pmap_bootstrap */
 
-TAILQ_HEAD(mmuq, mmuentry);
-struct mmuq segm_freelist, segm_lru, segm_locked;
-struct mmuq region_freelist, region_lru, region_locked;
-
-#define MMUQ_INIT(head)			TAILQ_INIT(head)
-
-#define MMUQ_REMOVE(elm, field)		do { 	\
-	TAILQ_REMOVE(elm->me_queue, elm,field); \
-	elm->me_queue = NULL;			\
-} while (/*CONSTCOND*/0)
-
-#define MMUQ_INSERT_TAIL(head, elm, field) do {	\
-	TAILQ_INSERT_TAIL(head, elm, field);	\
-	elm->me_queue = head;			\
-} while (/*CONSTCOND*/0)
+#if defined(SUN4) || defined(SUN4C)
+struct mmuentry segm_freelist, segm_lru, segm_locked;
+#if defined(SUN4_MMU3L)
+struct mmuentry region_freelist, region_lru, region_locked;
+#endif
+/*
+ * We use a double linked list looping through its static head (which
+ * alway remains on the list), so we can remove any other member from
+ * a list without knowing which list it is on.
+ */
+static void inline
+mmuq_remove(struct mmuentry *e)
+{
+	e->me_list.next->me_list.prev = e->me_list.prev;
+	e->me_list.prev->me_list.next = e->me_list.next;
+}
+
+static void inline
+mmuq_init(struct mmuentry *e)
+{
+	memset(e, 0, sizeof(*e));
+	e->me_list.next = e;
+	e->me_list.prev = e;
+}
+
+static inline struct mmuentry *
+mmuq_first(struct mmuentry *head)
+{
+	KASSERT(head->me_list.next != head);
+	return head->me_list.next;
+}
+
+static inline bool
+mmuq_empty(struct mmuentry *head)
+{
+	return head->me_list.next == head;
+}
+
+static inline void
+mmuq_insert_tail(struct mmuentry *head, struct mmuentry *e)
+{
+	e->me_list.prev = head->me_list.prev;
+	e->me_list.next = head;
+	head->me_list.prev->me_list.next = e;
+	head->me_list.prev = e;
+}
+#endif
 
-#define MMUQ_EMPTY(head)		TAILQ_EMPTY(head)
-#define MMUQ_FIRST(head)		TAILQ_FIRST(head)
 
 int	seginval;		/* [4/4c] the invalid segment number */
 int	reginval;		/* [4/3mmu] the invalid region number */
@@ -912,7 +942,7 @@ pgt_page_free(struct pool *pp, void *v)
 {
 	vaddr_t va;
 	paddr_t pa;
-	bool rv __diagused;
+	bool rv;
 
 	va = (vaddr_t)v;
 	rv = pmap_extract(pmap_kernel(), va, &pa);
@@ -1545,10 +1575,10 @@ mmu_setup4m_L3(int pagtblptd, struct seg
 /*
  * MMU management.
  */
-static int	me_alloc(struct mmuq *, struct pmap *, int, int);
+static int	me_alloc(struct mmuentry *, struct pmap *, int, int);
 static void	me_free(struct pmap *, u_int);
 #if defined(SUN4_MMU3L)
-static int	region_alloc(struct mmuq *, struct pmap *, int);
+static int	region_alloc(struct mmuentry *, struct pmap *, int);
 static void	region_free(struct pmap *, u_int);
 #endif
 
@@ -1568,7 +1598,7 @@ static void	region_free(struct pmap *, u
  */
 
 static inline int
-me_alloc(struct mmuq *mh, struct pmap *newpm, int newvreg, int newvseg)
+me_alloc(struct mmuentry *mh, struct pmap *newpm, int newvreg, int newvseg)
 {
 	struct mmuentry *me;
 	struct pmap *pm;
@@ -1578,16 +1608,16 @@ me_alloc(struct mmuq *mh, struct pmap *n
 	struct segmap *sp;
 
 	/* try free list first */
-	if (!MMUQ_EMPTY(&segm_freelist)) {
-		me = MMUQ_FIRST(&segm_freelist);
-		MMUQ_REMOVE(me, me_list);
+	if (!mmuq_empty(&segm_freelist)) {
+		me = mmuq_first(&segm_freelist);
+		mmuq_remove(me);
 #ifdef DEBUG
 		if (me->me_pmap != NULL)
 			panic("me_alloc: freelist entry has pmap");
 		if (pmapdebug & PDB_MMU_ALLOC)
 			printf("me_alloc: got pmeg %d\n", me->me_cookie);
 #endif
-		MMUQ_INSERT_TAIL(mh, me, me_list);
+		mmuq_insert_tail(mh, me);
 
 		/* onto on pmap chain; pmap is already locked, if needed */
 		TAILQ_INSERT_TAIL(&newpm->pm_seglist, me, me_pmchain);
@@ -1611,10 +1641,10 @@ me_alloc(struct mmuq *mh, struct pmap *n
 	}
 
 	/* no luck, take head of LRU list */
-	if (MMUQ_EMPTY(&segm_lru))
+	if (mmuq_empty(&segm_lru))
 		panic("me_alloc: all pmegs gone");
 
-	me = MMUQ_FIRST(&segm_lru);
+	me = mmuq_first(&segm_lru);
 	pm = me->me_pmap;
 #ifdef DEBUG
 	if (pmapdebug & (PDB_MMU_ALLOC | PDB_MMU_STEAL))
@@ -1628,8 +1658,8 @@ me_alloc(struct mmuq *mh, struct pmap *n
 	 * Remove from LRU list, and insert at end of new list
 	 * (probably the LRU list again, but so what?).
 	 */
-	MMUQ_REMOVE(me, me_list);
-	MMUQ_INSERT_TAIL(mh, me, me_list);
+	mmuq_remove(me);
+	mmuq_insert_tail(mh, me);
 
 #ifdef DIAGNOSTIC
 	if (mh == &segm_locked) {
@@ -1799,7 +1829,7 @@ me_free(struct pmap *pm, u_int pmeg)
 	TAILQ_REMOVE(&pm->pm_seglist, me, me_pmchain);
 
 	/* off LRU or lock chain */
-	MMUQ_REMOVE(me, me_list);
+	mmuq_remove(me);
 #ifdef DIAGNOSTIC
 	if (me->me_statp == NULL)
 		panic("me_statp");
@@ -1809,7 +1839,7 @@ me_free(struct pmap *pm, u_int pmeg)
 
 	/* no associated pmap; on free list */
 	me->me_pmap = NULL;
-	MMUQ_INSERT_TAIL(&segm_freelist, me, me_list);
+	mmuq_insert_tail(&segm_freelist, me);
 #ifdef DIAGNOSTIC
 	pmap_stats.ps_npmeg_free++;
 #endif
@@ -1820,7 +1850,7 @@ me_free(struct pmap *pm, u_int pmeg)
 /* XXX - Merge with segm_alloc/segm_free ? */
 
 int
-region_alloc(struct mmuq *mh, struct pmap *newpm, int newvr)
+region_alloc(struct mmuentry *mh, struct pmap *newpm, int newvr)
 {
 	struct mmuentry *me;
 	struct pmap *pm;
@@ -1828,16 +1858,16 @@ region_alloc(struct mmuq *mh, struct pma
 	struct regmap *rp;
 
 	/* try free list first */
-	if (!MMUQ_EMPTY(&region_freelist)) {
-		me = MMUQ_FIRST(&region_freelist);
-		MMUQ_REMOVE(me, me_list);
+	if (!mmuq_empty(&region_freelist)) {
+		me = mmuq_first(&region_freelist);
+		mmuq_remove(me);
 #ifdef DEBUG
 		if (me->me_pmap != NULL)
 			panic("region_alloc: freelist entry has pmap");
 		if (pmapdebug & PDB_MMUREG_ALLOC)
 			printf("region_alloc: got smeg 0x%x\n", me->me_cookie);
 #endif
-		MMUQ_INSERT_TAIL(mh, me, me_list);
+		mmuq_insert_tail(mh, me);
 
 		/* onto on pmap chain; pmap is already locked, if needed */
 		TAILQ_INSERT_TAIL(&newpm->pm_reglist, me, me_pmchain);
@@ -1850,10 +1880,10 @@ region_alloc(struct mmuq *mh, struct pma
 	}
 
 	/* no luck, take head of LRU list */
-	if (MMUQ_EMPTY(&region_lru))
+	if (mmuq_empty(&region_lru))
 		panic("region_alloc: all smegs gone");
 
-	me = MMUQ_FIRST(&region_lru);
+	me = mmuq_first(&region_lru);
 
 	pm = me->me_pmap;
 	if (pm == NULL)
@@ -1869,8 +1899,8 @@ region_alloc(struct mmuq *mh, struct pma
 	 * Remove from LRU list, and insert at end of new list
 	 * (probably the LRU list again, but so what?).
 	 */
-	MMUQ_REMOVE(me, me_list);
-	MMUQ_INSERT_TAIL(mh, me, me_list);
+	mmuq_remove(me);
+	mmuq_insert_tail(mh, me);
 
 	rp = &pm->pm_regmap[me->me_vreg];
 	ctx = getcontext4();
@@ -1925,16 +1955,16 @@ region_free(struct pmap *pm, u_int smeg)
 	TAILQ_REMOVE(&pm->pm_reglist, me, me_pmchain);
 
 	/* off LRU or lock chain */
-	MMUQ_REMOVE(me, me_list);
+	mmuq_remove(me);
 
 	/* no associated pmap; on free list */
 	me->me_pmap = NULL;
-	MMUQ_INSERT_TAIL(&region_freelist, me, me_list);
+	mmuq_insert_tail(&region_freelist, me);
 }
 
 static void
 mmu_pagein_reg(struct pmap *pm, struct regmap *rp, vaddr_t va,
-		int vr, struct mmuq *mh)
+		int vr, struct mmuentry *mh)
 {
 	int i, s, smeg;
 
@@ -1968,8 +1998,8 @@ mmu_pmeg_lock(int pmeg)
 {
 	struct mmuentry *me = &mmusegments[pmeg];
 
-	MMUQ_REMOVE(me, me_list);
-	MMUQ_INSERT_TAIL(&segm_locked, me, me_list);
+	mmuq_remove(me);
+	mmuq_insert_tail(&segm_locked, me);
 #ifdef DIAGNOSTIC
 	(*me->me_statp)--;
 	pmap_stats.ps_npmeg_locked++;
@@ -1982,8 +2012,8 @@ mmu_pmeg_unlock(int pmeg)
 {
 	struct mmuentry *me = &mmusegments[pmeg];
 
-	MMUQ_REMOVE(me, me_list);
-	MMUQ_INSERT_TAIL(&segm_lru, me, me_list);
+	mmuq_remove(me);
+	mmuq_insert_tail(&segm_lru, me);
 #ifdef DIAGNOSTIC
 	(*me->me_statp)--;
 	pmap_stats.ps_npmeg_lru++;
@@ -1993,7 +2023,7 @@ mmu_pmeg_unlock(int pmeg)
 
 static void
 mmu_pagein_seg(struct pmap *pm, struct segmap *sp, vaddr_t va,
-		int vr, int vs, struct mmuq *mh)
+		int vr, int vs, struct mmuentry *mh)
 {
 	int s, i, pmeg, *pte;
 
@@ -2291,7 +2321,7 @@ ctx_free(struct pmap *pm)
 
 #if defined(SUN4M) || defined(SUN4D)
 	if (CPU_HAS_SRMMU) {
-		CPU_INFO_ITERATOR i;
+		int i;
 
 		cache_flush_context(ctx);
 		tlb_flush_context(ctx, PMAP_CPUSET(pm));
@@ -2637,7 +2667,7 @@ pv_changepte4m(struct vm_page *pg, int b
 		return;
 
 	for (; pv != NULL; pv = pv->pv_next) {
-		int tpte __diagused;
+		int tpte;
 		pm = pv->pv_pmap;
 		/* XXXSMP: should lock pm */
 		va = pv->pv_va;
@@ -3150,13 +3180,13 @@ pmap_bootstrap4_4c(void *top, int nctx, 
 
 	/* Initialize MMU resource queues */
 #if defined(SUN4_MMU3L)
-	MMUQ_INIT(&region_freelist);
-	MMUQ_INIT(&region_lru);
-	MMUQ_INIT(&region_locked);
-#endif
-	MMUQ_INIT(&segm_freelist);
-	MMUQ_INIT(&segm_lru);
-	MMUQ_INIT(&segm_locked);
+	mmuq_init(&region_freelist);
+	mmuq_init(&region_lru);
+	mmuq_init(&region_locked);
+#endif
+	mmuq_init(&segm_freelist);
+	mmuq_init(&segm_lru);
+	mmuq_init(&segm_locked);
 
 
 	/*
@@ -3310,8 +3340,8 @@ pmap_bootstrap4_4c(void *top, int nctx, 
 				for (i = 1; i < nctx; i++)
 					prom_setcontext(i, (void *)p, rcookie);
 
-				MMUQ_INSERT_TAIL(&region_locked,
-						  mmureg, me_list);
+				mmuq_insert_tail(&region_locked,
+						  mmureg);
 				TAILQ_INSERT_TAIL(&pmap_kernel()->pm_reglist,
 						  mmureg, me_pmchain);
 #ifdef DIAGNOSTIC
@@ -3334,7 +3364,7 @@ pmap_bootstrap4_4c(void *top, int nctx, 
 				prom_setcontext(i, (void *)p, scookie);
 
 		/* set up the mmu entry */
-		MMUQ_INSERT_TAIL(&segm_locked, mmuseg, me_list);
+		mmuq_insert_tail(&segm_locked, mmuseg);
 #ifdef DIAGNOSTIC
 		mmuseg->me_statp = &pmap_stats.ps_npmeg_locked;
 #endif
@@ -3412,7 +3442,7 @@ pmap_bootstrap4_4c(void *top, int nctx, 
 				rcookie++;
 			mmureg = &mmuregions[rcookie];
 			mmureg->me_cookie = rcookie;
-			MMUQ_INSERT_TAIL(&region_freelist, mmureg, me_list);
+			mmuq_insert_tail(&region_freelist, mmureg);
 #ifdef DIAGNOSTIC
 			mmuseg->me_statp = NULL;
 #endif
@@ -3425,7 +3455,7 @@ pmap_bootstrap4_4c(void *top, int nctx, 
 			scookie = zseg;
 		mmuseg = &mmusegments[scookie];
 		mmuseg->me_cookie = scookie;
-		MMUQ_INSERT_TAIL(&segm_freelist, mmuseg, me_list);
+		mmuq_insert_tail(&segm_freelist, mmuseg);
 		pmap_stats.ps_npmeg_free++;
 #ifdef DIAGNOSTIC
 		mmuseg->me_statp = NULL;

Reply via email to