Module Name:    src
Committed By:   matt
Date:           Wed Jul  3 21:37:35 UTC 2013

Modified Files:
        src/sys/arch/arm/arm32: pmap.c
        src/sys/arch/arm/include/arm32: pmap.h

Log Message:
Add l2pte_set and l2pte_reset inlines to set/reset a pte.  These will be
used to support > 4KB pages sizes.
Don't use >> L1_S_SHIFT, use L1_IDX() instead.


To generate a diff of this commit:
cvs rdiff -u -r1.261 -r1.262 src/sys/arch/arm/arm32/pmap.c
cvs rdiff -u -r1.120 -r1.121 src/sys/arch/arm/include/arm32/pmap.h

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/arm/arm32/pmap.c
diff -u src/sys/arch/arm/arm32/pmap.c:1.261 src/sys/arch/arm/arm32/pmap.c:1.262
--- src/sys/arch/arm/arm32/pmap.c:1.261	Wed Jul  3 15:30:24 2013
+++ src/sys/arch/arm/arm32/pmap.c	Wed Jul  3 21:37:35 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.261 2013/07/03 15:30:24 matt Exp $	*/
+/*	$NetBSD: pmap.c,v 1.262 2013/07/03 21:37:35 matt Exp $	*/
 
 /*
  * Copyright 2003 Wasabi Systems, Inc.
@@ -212,7 +212,7 @@
 #include <arm/cpuconf.h>
 #include <arm/arm32/katelib.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.261 2013/07/03 15:30:24 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.262 2013/07/03 21:37:35 matt Exp $");
 
 #ifdef PMAP_DEBUG
 
@@ -1496,8 +1496,6 @@ static int
 pmap_l2ptp_ctor(void *arg, void *v, int flags)
 {
 #ifndef PMAP_INCLUDE_PTE_SYNC
-	struct l2_bucket *l2b;
-	pt_entry_t *ptep, pte;
 	vaddr_t va = (vaddr_t)v & ~PGOFSET;
 
 	/*
@@ -1508,16 +1506,18 @@ pmap_l2ptp_ctor(void *arg, void *v, int 
 	 * page tables, we simply fix up the cache-mode here if it's not
 	 * correct.
 	 */
-	l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+	struct l2_bucket * const l2b = pmap_get_l2_bucket(pmap_kernel(), va);
 	KDASSERT(l2b != NULL);
-	ptep = &l2b->l2b_kva[l2pte_index(va)];
-	pte = *ptep;
+	pt_entry_t *ptep = &l2b->l2b_kva[l2pte_index(va)];
+	pt_entry_t opte = *ptep;
 
-	if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
+	if ((opte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
 		/*
 		 * Page tables must have the cache-mode set to Write-Thru.
 		 */
-		*ptep = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
+		const pt_entry_t npte = (pte & ~L2_S_CACHE_MASK)
+		    | pte_l2_s_cache_mode_pt;
+		l2pte_set(ptep, npte, opte);
 		PTE_SYNC(ptep);
 		cpu_tlb_flushD_SE(va);
 		cpu_cpwait();
@@ -1556,7 +1556,8 @@ pmap_pinit(pmap_t pm)
 		 * Map the vector page.
 		 */
 		pmap_enter(pm, vector_page, systempage.pv_pa,
-		    VM_PROT_READ, VM_PROT_READ | PMAP_WIRED);
+		    VM_PROT_READ | VM_PROT_EXECUTE,
+		    VM_PROT_READ | VM_PROT_EXECUTE | PMAP_WIRED);
 		pmap_update(pm);
 
 		pm->pm_pl1vec = pmap_l1_kva(pm) + L1_IDX(vector_page);
@@ -1730,8 +1731,6 @@ pmap_vac_me_user(struct vm_page_md *md, 
 {
 	pmap_t kpmap = pmap_kernel();
 	struct pv_entry *pv, *npv = NULL;
-	struct l2_bucket *l2b;
-	pt_entry_t *ptep, pte;
 	u_int entries = 0;
 	u_int writable = 0;
 	u_int cacheable_entries = 0;
@@ -1783,13 +1782,16 @@ pmap_vac_me_user(struct vm_page_md *md, 
 
 			pv->pv_flags |= PVF_NC;
 
-			l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
+			struct l2_bucket * const l2b
+			    = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
 			KDASSERT(l2b != NULL);
-			ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
-			pte = *ptep & ~L2_S_CACHE_MASK;
+			pt_entry_t * const ptep
+			    = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+			const pt_entry_t opte = *ptep;
+			pt_entry_t npte = opte & ~L2_S_CACHE_MASK;
 
 			if ((va != pv->pv_va || pm != pv->pv_pmap)
-			    && l2pte_valid(pte)) {
+			    && l2pte_valid(npte)) {
 #ifdef PMAP_CACHE_VIVT
 				pmap_cache_wbinv_page(pv->pv_pmap, pv->pv_va,
 				    true, pv->pv_flags);
@@ -1798,7 +1800,7 @@ pmap_vac_me_user(struct vm_page_md *md, 
 				    pv->pv_flags);
 			}
 
-			*ptep = pte;
+			l2pte_set(ptep, npte, opte);
 			PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
 		}
 		cpu_cpwait();
@@ -1815,17 +1817,21 @@ pmap_vac_me_user(struct vm_page_md *md, 
 
 			pv->pv_flags &= ~PVF_NC;
 
-			l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
+			struct l2_bucket * const l2b
+			    = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
 			KDASSERT(l2b != NULL);
-			ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
-			pte = (*ptep & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode;
+			pt_entry_t * const ptep
+			    = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+			const pt_entry_t opte = *ptep;
+			pt_entry_t npte = (opte & ~L2_S_CACHE_MASK)
+			    | pte_l2_s_cache_mode;
 
-			if (l2pte_valid(pte)) {
+			if (l2pte_valid(opte)) {
 				pmap_tlb_flush_SE(pv->pv_pmap, pv->pv_va,
 				    pv->pv_flags);
 			}
 
-			*ptep = pte;
+			l2pte_set(ptep, npte, opte);
 			PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
 		}
 	}
@@ -1839,8 +1845,6 @@ pmap_vac_me_harder(struct vm_page_md *md
 	struct pv_entry *pv;
 	vaddr_t tst_mask;
 	bool bad_alias;
-	struct l2_bucket *l2b;
-	pt_entry_t *ptep, pte, opte;
 	const u_int
 	    rw_mappings = md->urw_mappings + md->krw_mappings,
 	    ro_mappings = md->uro_mappings + md->kro_mappings;
@@ -2098,27 +2102,27 @@ pmap_vac_me_harder(struct vm_page_md *md
 	 * Turn cacheing on/off for all pages.
 	 */
 	SLIST_FOREACH(pv, &md->pvh_list, pv_link) {
-		l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
+		struct l2_bucket * const l2b = pmap_get_l2_bucket(pv->pv_pmap,
+		    pv->pv_va);
 		KDASSERT(l2b != NULL);
-		ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
-		opte = *ptep;
-		pte = opte & ~L2_S_CACHE_MASK;
+		pt_entry_t * const ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+		const pt_entry_t opte = *ptep;
+		pt_entry_t npte = opte & ~L2_S_CACHE_MASK;
 		if (bad_alias) {
 			pv->pv_flags |= PVF_NC;
 		} else {
 			pv->pv_flags &= ~PVF_NC;
-			pte |= pte_l2_s_cache_mode;
+			npte |= pte_l2_s_cache_mode;
 		}
 
-		if (opte == pte)	/* only update is there's a change */
+		if (opte == npte)	/* only update is there's a change */
 			continue;
 
-		if (l2pte_valid(pte)) {
-			pmap_tlb_flush_SE(pv->pv_pmap, pv->pv_va,
-			    pv->pv_flags);
+		if (l2pte_valid(npte)) {
+			pmap_tlb_flush_SE(pv->pv_pmap, pv->pv_va, pv->pv_flags);
 		}
 
-		*ptep = pte;
+		l2pte_set(ptep, npte, opte);
 		PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
 	}
 }
@@ -2133,17 +2137,14 @@ pmap_vac_me_harder(struct vm_page_md *md
 static void
 pmap_clearbit(struct vm_page_md *md, paddr_t pa, u_int maskbits)
 {
-	struct l2_bucket *l2b;
 	struct pv_entry *pv;
-	pt_entry_t *ptep, npte, opte;
 	pmap_t pm;
 	vaddr_t va;
 	u_int oflags;
 #ifdef PMAP_CACHE_VIPT
 	const bool want_syncicache = PV_IS_EXEC_P(md->pvh_attrs);
-	bool need_syncicache = false;
-	bool did_syncicache = false;
 	bool need_vac_me_harder = false;
+	bool need_syncicache = false;
 #endif
 
 	NPDEBUG(PDB_BITS,
@@ -2155,8 +2156,9 @@ pmap_clearbit(struct vm_page_md *md, pad
 	 * If we might want to sync the I-cache and we've modified it,
 	 * then we know we definitely need to sync or discard it.
 	 */
-	if (want_syncicache)
+	if (want_syncicache) {
 		need_syncicache = md->pvh_attrs & PVF_MOD;
+	}
 #endif
 	/*
 	 * Clear saved attributes (modify, reference)
@@ -2164,7 +2166,7 @@ pmap_clearbit(struct vm_page_md *md, pad
 	md->pvh_attrs &= ~(maskbits & (PVF_MOD | PVF_REF));
 
 	if (SLIST_EMPTY(&md->pvh_list)) {
-#ifdef PMAP_CACHE_VIPT
+#if defined(PMAP_CACHE_VIPT)
 		if (need_syncicache) {
 			/*
 			 * No one has it mapped, so just discard it.  The next
@@ -2193,11 +2195,12 @@ pmap_clearbit(struct vm_page_md *md, pad
 
 		pmap_acquire_pmap_lock(pm);
 
-		l2b = pmap_get_l2_bucket(pm, va);
+		struct l2_bucket * const l2b = pmap_get_l2_bucket(pm, va);
 		KDASSERT(l2b != NULL);
 
-		ptep = &l2b->l2b_kva[l2pte_index(va)];
-		npte = opte = *ptep;
+		pt_entry_t * const ptep = &l2b->l2b_kva[l2pte_index(va)];
+		const pt_entry_t opte = *ptep;
+		pt_entry_t npte = opte;
 
 		NPDEBUG(PDB_BITS,
 		    printf(
@@ -2292,8 +2295,9 @@ pmap_clearbit(struct vm_page_md *md, pad
 		}
 
 		if (npte != opte) {
-			*ptep = npte;
+			l2pte_set(ptep, npte, opte);
 			PTE_SYNC(ptep);
+
 			/* Flush the TLB entry if a current pmap. */
 			pmap_tlb_flush_SE(pm, pv->pv_va, oflags);
 		}
@@ -2309,10 +2313,11 @@ pmap_clearbit(struct vm_page_md *md, pad
 	/*
 	 * If we need to sync the I-cache and we haven't done it yet, do it.
 	 */
-	if (need_syncicache && !did_syncicache) {
+	if (need_syncicache) {
 		pmap_syncicache_page(md, pa);
 		PMAPCOUNT(exec_synced_clearbit);
 	}
+
 	/*
 	 * If we are changing this to read-only, we need to call vac_me_harder
 	 * so we can change all the read-only pages to cacheable.  We pretend
@@ -2430,10 +2435,11 @@ pmap_syncicache_page(struct vm_page_md *
 	/*
 	 * Set up a PTE with the right coloring to flush existing cache lines.
 	 */
-	*ptep = L2_S_PROTO |
+	const pt_entry_t npte = L2_S_PROTO |
 	    pa
 	    | L2_S_PROT(PTE_KERNEL, VM_PROT_READ|VM_PROT_WRITE)
 	    | pte_l2_s_cache_mode;
+	l2pte_set(ptep, npte, 0);
 	PTE_SYNC(ptep);
 
 	/*
@@ -2443,7 +2449,7 @@ pmap_syncicache_page(struct vm_page_md *
 	/*
 	 * Unmap the page.
 	 */
-	*ptep = 0;
+	l2pte_reset(ptep);
 	PTE_SYNC(ptep);
 	pmap_tlb_flush_SE(pmap_kernel(), cdstp + va_offset, PVF_REF | PVF_EXEC);
 
@@ -2510,7 +2516,7 @@ pmap_flush_page(struct vm_page_md *md, p
 	for (; va_offset <= end_va; va_offset += PAGE_SIZE) {
 		const size_t pte_offset = va_offset >> PGSHIFT;
 		pt_entry_t * const ptep = &cdst_pte[pte_offset];
-		const pt_entry_t oldpte = *ptep;
+		const pt_entry_t opte = *ptep;
 
 		if (flush == PMAP_FLUSH_SECONDARY
 		    && va_offset == (md->pvh_attrs & arm_cache_prefer_mask))
@@ -2522,14 +2528,16 @@ pmap_flush_page(struct vm_page_md *md, p
 		 * Set up a PTE with the right coloring to flush
 		 * existing cache entries.
 		 */
-		*ptep = L2_S_PROTO
+		const pt_entry_t npte = L2_S_PROTO
 		    | pa
 		    | L2_S_PROT(PTE_KERNEL, VM_PROT_READ|VM_PROT_WRITE)
 		    | pte_l2_s_cache_mode;
+		l2pte_set(ptep, npte, opte);
 		PTE_SYNC(ptep);
 
 		/*
-		 * Flush it.
+		 * Flush it.  Make sure to flush secondary cache too since
+		 * bus_dma will ignore uncached pages.
 		 */
                 vaddr_t va = cdstp + va_offset;  
 		if (scache_line_size != 0) {
@@ -2553,7 +2561,7 @@ pmap_flush_page(struct vm_page_md *md, p
 		 * pmap_zero_page or pmap_copy_page which was already using
 		 * this pte.
 		 */
-		*ptep = oldpte;
+		l2pte_set(ptep, opte, npte);
 		PTE_SYNC(ptep);
 		pmap_tlb_flush_SE(pmap_kernel(), cdstp + va_offset,
 		    PVF_REF | PVF_EXEC);
@@ -2665,7 +2673,7 @@ pmap_page_remove(struct vm_page_md *md, 
 		/*
 		 * Invalidate the PTEs.
 		 */
-		*ptep = 0;
+		l2pte_reset(ptep);
 		PTE_SYNC_CURRENT(pm, ptep);
 		pmap_free_l2_bucket(pm, l2b, 1);
 
@@ -2775,7 +2783,6 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 	struct l2_bucket *l2b;
 	struct vm_page *pg, *opg;
 	struct pv_entry *pv;
-	pt_entry_t *ptep, npte, opte;
 	u_int nflags;
 	u_int oflags;
 #ifdef ARM_HAS_VBAR
@@ -2820,9 +2827,9 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 		}
 		panic("pmap_enter: failed to allocate L2 bucket");
 	}
-	ptep = &l2b->l2b_kva[l2pte_index(va)];
-	opte = *ptep;
-	npte = pa;
+	pt_entry_t *ptep = &l2b->l2b_kva[l2pte_index(va)];
+	const pt_entry_t opte = *ptep;
+	pt_entry_t npte = pa;
 	oflags = 0;
 
 	if (opte) {
@@ -3021,7 +3028,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 	if (npte != opte) {
 		bool is_cached = pmap_is_cached(pm);
 
-		*ptep = npte;
+		l2pte_set(ptep, npte, opte);
 		PTE_SYNC(ptep);
 		if (is_cached) {
 			/*
@@ -3104,9 +3111,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 void
 pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva)
 {
-	struct l2_bucket *l2b;
 	vaddr_t next_bucket;
-	pt_entry_t *ptep;
 	u_int cleanlist_idx, total, cnt;
 	struct {
 		vaddr_t va;
@@ -3139,35 +3144,34 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
 		if (next_bucket > eva)
 			next_bucket = eva;
 
-		l2b = pmap_get_l2_bucket(pm, sva);
+		struct l2_bucket * const l2b = pmap_get_l2_bucket(pm, sva);
 		if (l2b == NULL) {
 			sva = next_bucket;
 			continue;
 		}
 
-		ptep = &l2b->l2b_kva[l2pte_index(sva)];
-
-		for (mappings = 0; sva < next_bucket; sva += PAGE_SIZE, ptep++){
-			struct vm_page *pg;
-			pt_entry_t pte;
-			paddr_t pa;
+		pt_entry_t *ptep = &l2b->l2b_kva[l2pte_index(sva)];
 
-			pte = *ptep;
+		for (mappings = 0;
+		     sva < next_bucket;
+		     sva += PAGE_SIZE, ptep += PAGE_SIZE / L2_S_SIZE) {
+			pt_entry_t opte = *ptep;
 
-			if (pte == 0) {
+			if (opte == 0) {
 				/* Nothing here, move along */
 				continue;
 			}
 
-			pa = l2pte_pa(pte);
 			u_int flags = PVF_REF;
+			paddr_t pa = l2pte_pa(opte);
+			struct vm_page * const pg = PHYS_TO_VM_PAGE(pa);
 
 			/*
 			 * Update flags. In a number of circumstances,
 			 * we could cluster a lot of these and do a
 			 * number of sequential pages in one go.
 			 */
-			if ((pg = PHYS_TO_VM_PAGE(pa)) != NULL) {
+			if (pg != NULL) {
 				struct vm_page_md *md = VM_PAGE_TO_MD(pg);
 				struct pv_entry *pv;
 
@@ -3185,13 +3189,13 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
 			}
 			mappings++;
 
-			if (!l2pte_valid(pte)) {
+			if (!l2pte_valid(opte)) {
 				/*
 				 * Ref/Mod emulation is still active for this
 				 * mapping, therefore it is has not yet been
 				 * accessed. No need to frob the cache/tlb.
 				 */
-				*ptep = 0;
+				l2pte_reset(ptep);
 				PTE_SYNC_CURRENT(pm, ptep);
 				continue;
 			}
@@ -3216,15 +3220,15 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
 				 */
 				for (cnt = 0;
 				     cnt < PMAP_REMOVE_CLEAN_LIST_SIZE; cnt++) {
-					*cleanlist[cnt].ptep = 0;
+					l2pte_reset(cleanlist[cnt].ptep);
 					PTE_SYNC(cleanlist[cnt].ptep);
 				}
-				*ptep = 0;
+				l2pte_reset(ptep);
 				PTE_SYNC(ptep);
 				cleanlist_idx++;
 				pm->pm_remove_all = true;
 			} else {
-				*ptep = 0;
+				l2pte_reset(ptep);
 				PTE_SYNC(ptep);
 				if (pm->pm_remove_all == false) {
 					pmap_tlb_flush_SE(pm, sva, flags);
@@ -3249,7 +3253,7 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
 					pmap_tlb_flush_SE(pm, clva,
 					    PVF_REF | flags);
 				}
-				*cleanlist[cnt].ptep = 0;
+				l2pte_reset(cleanlist[cnt].ptep);
 				PTE_SYNC_CURRENT(pm, cleanlist[cnt].ptep);
 			}
 
@@ -3323,8 +3327,6 @@ pmap_kremove_pg(struct vm_page *pg, vadd
 void
 pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags)
 {
-	struct l2_bucket *l2b;
-	pt_entry_t *ptep, opte;
 #ifdef PMAP_CACHE_VIVT
 	struct vm_page *pg = (flags & PMAP_KMPAGE) ? PHYS_TO_VM_PAGE(pa) : NULL;
 #endif
@@ -3339,11 +3341,11 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
 	    printf("pmap_kenter_pa: va 0x%08lx, pa 0x%08lx, prot 0x%x\n",
 	    va, pa, prot));
 
-	l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+	struct l2_bucket * const l2b = pmap_get_l2_bucket(pmap_kernel(), va);
 	KDASSERT(l2b != NULL);
 
-	ptep = &l2b->l2b_kva[l2pte_index(va)];
-	opte = *ptep;
+	pt_entry_t * const ptep = &l2b->l2b_kva[l2pte_index(va)];
+	const pt_entry_t opte = *ptep;
 
 	if (opte == 0) {
 		PMAPCOUNT(kenter_mappings);
@@ -3371,8 +3373,9 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
 		}
 	}
 
-	*ptep = L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot)
+	const pt_entry_t npte = L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot)
 	    | ((flags & PMAP_NOCACHE) ? 0 : pte_l2_s_cache_mode);
+	l2pte_set(ptep, npte, opte);
 	PTE_SYNC(ptep);
 
 	if (pg) {
@@ -3437,11 +3440,8 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
 void
 pmap_kremove(vaddr_t va, vsize_t len)
 {
-	struct l2_bucket *l2b;
-	pt_entry_t *ptep, *sptep, opte;
 	vaddr_t next_bucket, eva;
 	u_int mappings;
-	struct vm_page *opg;
 
 	PMAPCOUNT(kenter_unmappings);
 
@@ -3455,16 +3455,17 @@ pmap_kremove(vaddr_t va, vsize_t len)
 		if (next_bucket > eva)
 			next_bucket = eva;
 
-		l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+		struct l2_bucket * const l2b = pmap_get_l2_bucket(pmap_kernel(), va);
 		KDASSERT(l2b != NULL);
 
-		sptep = ptep = &l2b->l2b_kva[l2pte_index(va)];
+		pt_entry_t * const sptep = &l2b->l2b_kva[l2pte_index(va)];
+		pt_entry_t *ptep = sptep;
 		mappings = 0;
 
 		while (va < next_bucket) {
-			opte = *ptep;
-			opg = PHYS_TO_VM_PAGE(l2pte_pa(opte));
-			if (opg) {
+			const pt_entry_t opte = *ptep;
+			struct vm_page *opg = PHYS_TO_VM_PAGE(l2pte_pa(opte));
+			if (opg != NULL) {
 				struct vm_page_md *omd = VM_PAGE_TO_MD(opg);
 
 				if (omd->pvh_attrs & PVF_KMPAGE) {
@@ -3493,11 +3494,11 @@ pmap_kremove(vaddr_t va, vsize_t len)
 				cpu_tlb_flushD_SE(va);
 			}
 			if (opte) {
-				*ptep = 0;
+				l2pte_reset(ptep);
 				mappings++;
 			}
 			va += PAGE_SIZE;
-			ptep++;
+			ptep += PAGE_SIZE / L2_S_SIZE;
 		}
 		KDASSERT(mappings <= l2b->l2b_occupancy);
 		l2b->l2b_occupancy -= mappings;
@@ -3577,9 +3578,6 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
 	struct l2_bucket *l2b;
 	pt_entry_t *ptep, pte;
 	vaddr_t next_bucket;
-	u_int flags;
-	u_int clr_mask;
-	int flush;
 
 	NPDEBUG(PDB_PROTECT,
 	    printf("pmap_protect: pm %p sva 0x%lx eva 0x%lx prot 0x%x\n",
@@ -3600,9 +3598,9 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
 
 	pmap_acquire_pmap_lock(pm);
 
-	flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1;
-	flags = 0;
-	clr_mask = PVF_WRITE | ((prot & VM_PROT_EXECUTE) ? 0 : PVF_EXEC);
+	const bool flush = eva - sva >= PAGE_SIZE * 4;
+	u_int clr_mask = PVF_WRITE | ((prot & VM_PROT_EXECUTE) ? 0 : PVF_EXEC);
+	u_int flags = 0;
 
 	while (sva < eva) {
 		next_bucket = L2_NEXT_BUCKET(sva);
@@ -3651,8 +3649,7 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
 					f = PVF_REF | PVF_EXEC;
 				}
 
-				if (flush >= 0) {
-					flush++;
+				if (flush) {
 					flags |= f;
 				} else {
 					pmap_tlb_flush_SE(pm, sva, f);
@@ -3664,15 +3661,15 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
 		}
 	}
 
-	pmap_release_pmap_lock(pm);
-
 	if (flush) {
-		if (PV_BEEN_EXECD(flags))
+		if (PV_BEEN_EXECD(flags)) {
 			pmap_tlb_flushID(pm);
-		else
-		if (PV_BEEN_REFD(flags))
+		} else if (PV_BEEN_REFD(flags)) {
 			pmap_tlb_flushD(pm);
+		}
 	}
+
+	pmap_release_pmap_lock(pm);
 }
 
 void
@@ -5699,9 +5696,9 @@ pmap_map_section(vaddr_t l1pt, vaddr_t v
 		break;
 	}
 
-	pde[va >> L1_S_SHIFT] = L1_S_PROTO | pa |
+	pde[L1_IDX(va)] = L1_S_PROTO | pa |
 	    L1_S_PROT(PTE_KERNEL, prot) | fl | L1_S_DOM(PMAP_DOMAIN_KERNEL);
-	PTE_SYNC(&pde[va >> L1_S_SHIFT]);
+	PTE_SYNC(&pde[L1_IDX(va)]);
 }
 
 /*
@@ -5713,47 +5710,46 @@ void
 pmap_map_entry(vaddr_t l1pt, vaddr_t va, paddr_t pa, int prot, int cache)
 {
 	pd_entry_t *pde = (pd_entry_t *) l1pt;
-	pt_entry_t fl;
-	pt_entry_t *pte;
+	pt_entry_t npte;
+	pt_entry_t *ptep;
 
 	KASSERT(((va | pa) & PGOFSET) == 0);
 
 	switch (cache) {
 	case PTE_NOCACHE:
 	default:
-		fl = 0;
+		npte = 0;
 		break;
 
 	case PTE_CACHE:
-		fl = pte_l2_s_cache_mode;
+		npte = pte_l2_s_cache_mode;
 		break;
 
 	case PTE_PAGETABLE:
-		fl = pte_l2_s_cache_mode_pt;
+		npte = pte_l2_s_cache_mode_pt;
 		break;
 	}
 
-	if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
+	if ((pde[L1_IDX(va)] & L1_TYPE_MASK) != L1_TYPE_C)
 		panic("pmap_map_entry: no L2 table for VA 0x%08lx", va);
 
 #ifndef ARM32_NEW_VM_LAYOUT
-	pte = (pt_entry_t *)
-	    kernel_pt_lookup(pde[va >> L1_S_SHIFT] & L2_S_FRAME);
+	ptep = (pt_entry_t *)
+	    kernel_pt_lookup(pde[L1_IDX(va)] & L2_S_FRAME);
 #else
-	pte = (pt_entry_t *) kernel_pt_lookup(pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+	ptep = (pt_entry_t *) kernel_pt_lookup(pde[L1_IDX(va)] & L1_C_ADDR_MASK);
 #endif
-	if (pte == NULL)
+	if (ptep == NULL)
 		panic("pmap_map_entry: can't find L2 table for VA 0x%08lx", va);
 
-	fl |= L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot);
+	npte |= L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot);
 #ifndef ARM32_NEW_VM_LAYOUT
-	pte += (va >> PGSHIFT) & 0x3ff;
+	ptep += (va >> PGSHIFT) & 0x3ff;
 #else
-	pte += l2pte_index(va);
-	    L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) | fl;
+	ptep += l2pte_index(va);
 #endif
-	*pte = fl;
-	PTE_SYNC(pte);
+	l2pte_set(ptep, npte, 0);
+	PTE_SYNC(ptep);
 }
 
 /*
@@ -5766,7 +5762,7 @@ void
 pmap_link_l2pt(vaddr_t l1pt, vaddr_t va, pv_addr_t *l2pv)
 {
 	pd_entry_t *pde = (pd_entry_t *) l1pt, proto;
-	u_int slot = va >> L1_S_SHIFT;
+	u_int slot = L1_IDX(va);
 
 #ifndef ARM32_NEW_VM_LAYOUT
 	KASSERT((va & ((L1_S_SIZE * 4) - 1)) == 0);
@@ -5779,10 +5775,10 @@ pmap_link_l2pt(vaddr_t l1pt, vaddr_t va,
 #ifdef ARM32_NEW_VM_LAYOUT
 	PTE_SYNC(&pde[slot]);
 #else
-	pde[slot + 1] = proto | (l2pv->pv_pa + 0x400);
-	pde[slot + 2] = proto | (l2pv->pv_pa + 0x800);
-	pde[slot + 3] = proto | (l2pv->pv_pa + 0xc00);
-	PTE_SYNC_RANGE(&pde[slot + 0], 4);
+	for (u_int off = 0, i = 0; off < PAGE_SIZE; off += L2_T_SIZE, i++) {
+		pde[slot + i] = proto | (l2pv->pv_pa + off);
+	}
+	PTE_SYNC_RANGE(&pde[slot + 0], PAGE_SIZE / L2_T_SIZE);
 #endif
 
 	SLIST_INSERT_HEAD(&kernel_pt_list, l2pv, pv_list);
@@ -5838,6 +5834,7 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
 	size = resid;
 
 	while (resid > 0) {
+		size_t l1idx = L1_IDX(va);
 #if (ARM_MMU_V6 + ARM_MMU_V7) > 0
 		/* See if we can use a supersection mapping. */
 		if (L1_SS_PROTO && L1_SS_MAPPABLE_P(va, pa, resid)) {
@@ -5847,7 +5844,7 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
 #ifdef VERBOSE_INIT_ARM
 			printf("sS");
 #endif
-			for (size_t s = va >> L1_S_SHIFT,
+			for (size_t s = l1idx,
 			     e = s + L1_SS_SIZE / L1_S_SIZE;
 			     s < e;
 			     s++) {
@@ -5865,10 +5862,10 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
 #ifdef VERBOSE_INIT_ARM
 			printf("S");
 #endif
-			pdep[va >> L1_S_SHIFT] = L1_S_PROTO | pa |
+			pdep[l1idx] = L1_S_PROTO | pa |
 			    L1_S_PROT(PTE_KERNEL, prot) | f1 |
 			    L1_S_DOM(PMAP_DOMAIN_KERNEL);
-			PTE_SYNC(&pdep[va >> L1_S_SHIFT]);
+			PTE_SYNC(&pdep[l1idx]);
 			va += L1_S_SIZE;
 			pa += L1_S_SIZE;
 			resid -= L1_S_SIZE;
@@ -5880,15 +5877,15 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
 		 * one is actually in the corresponding L1 slot
 		 * for the current VA.
 		 */
-		if ((pdep[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
+		if ((pdep[l1idx] & L1_TYPE_MASK) != L1_TYPE_C)
 			panic("pmap_map_chunk: no L2 table for VA 0x%08lx", va);
 
 #ifndef ARM32_NEW_VM_LAYOUT
 		pte = (pt_entry_t *)
-		    kernel_pt_lookup(pdep[va >> L1_S_SHIFT] & L2_S_FRAME);
+		    kernel_pt_lookup(pdep[l1idx] & L2_S_FRAME);
 #else
 		pte = (pt_entry_t *) kernel_pt_lookup(
-		    pdep[L1_IDX(va)] & L1_C_ADDR_MASK);
+		    pdep[l1idx] & L1_C_ADDR_MASK);
 #endif
 		if (pte == NULL)
 			panic("pmap_map_chunk: can't find L2 table for VA"
@@ -5922,15 +5919,15 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
 #ifdef VERBOSE_INIT_ARM
 		printf("P");
 #endif
-#ifndef ARM32_NEW_VM_LAYOUT
-		pte[(va >> PGSHIFT) & 0x3ff] =
+		pt_entry_t npte = 
 		    L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) | f2s;
-		PTE_SYNC(&pte[(va >> PGSHIFT) & 0x3ff]);
+#ifndef ARM32_NEW_VM_LAYOUT
+		pt_entry_t *ptep = &pte[(va >> PGSHIFT) & 0x3ff];
 #else
-		pte[l2pte_index(va)] =
-		    L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) | f2s;
-		PTE_SYNC(&pte[l2pte_index(va)]);
+		pt_entry_t *ptep = &pte[l2pte_index(va)];
 #endif
+		l2pte_set(ptep, npte, 0);
+		PTE_SYNC(ptep);
 		va += PAGE_SIZE;
 		pa += PAGE_SIZE;
 		resid -= PAGE_SIZE;
@@ -6381,7 +6378,6 @@ xscale_setup_minidata(vaddr_t l1pt, vadd
 	extern vaddr_t xscale_minidata_clean_addr;
 	extern vsize_t xscale_minidata_clean_size; /* already initialized */
 	pd_entry_t *pde = (pd_entry_t *) l1pt;
-	pt_entry_t *pte;
 	vsize_t size;
 	uint32_t auxctl;
 
@@ -6392,23 +6388,27 @@ xscale_setup_minidata(vaddr_t l1pt, vadd
 
 	for (; size != 0;
 	     va += L2_S_SIZE, pa += L2_S_SIZE, size -= L2_S_SIZE) {
+		const size_t l1idx = L1_IDX(va);
 #ifndef ARM32_NEW_VM_LAYOUT
-		pte = (pt_entry_t *)
-		    kernel_pt_lookup(pde[va >> L1_S_SHIFT] & L2_S_FRAME);
+		pt_entry_t *ptep = (pt_entry_t *)
+		    kernel_pt_lookup(pde[l1idx] & L2_S_FRAME);
 #else
-		pte = (pt_entry_t *) kernel_pt_lookup(
-		    pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+		pt_entry_t *ptep = (pt_entry_t *) kernel_pt_lookup(
+		    pde[l1idx] & L1_C_ADDR_MASK);
 #endif
-		if (pte == NULL)
+		if (ptep == NULL)
 			panic("xscale_setup_minidata: can't find L2 table for "
 			    "VA 0x%08lx", va);
+		
 #ifndef ARM32_NEW_VM_LAYOUT
-		pte[(va >> PGSHIFT) & 0x3ff] =
+		ptep += (va >> PGSHIFT) & 0x3ff;
 #else
-		pte[l2pte_index(va)] =
+		ptep += l2pte_index(va);
 #endif
-		    L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, VM_PROT_READ) |
-		    L2_C | L2_XS_T_TEX(TEX_XSCALE_X);
+		pt_entry_t opte = *ptep;
+		l2pte_set(ptep, 
+		    L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, VM_PROT_READ)
+		    | L2_C | L2_XS_T_TEX(TEX_XSCALE_X), opte);
 	}
 
 	/*
@@ -6437,8 +6437,6 @@ xscale_setup_minidata(vaddr_t l1pt, vadd
 void
 pmap_uarea(vaddr_t va)
 {
-	struct l2_bucket *l2b;
-	pt_entry_t *ptep, *sptep, pte;
 	vaddr_t next_bucket, eva;
 
 #if (ARM_NMMUS > 1)
@@ -6453,19 +6451,20 @@ pmap_uarea(vaddr_t va)
 		if (next_bucket > eva)
 			next_bucket = eva;
 
-		l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+		struct l2_bucket *l2b = pmap_get_l2_bucket(pmap_kernel(), va);
 		KDASSERT(l2b != NULL);
 
-		sptep = ptep = &l2b->l2b_kva[l2pte_index(va)];
+		pt_entry_t * const sptep = &l2b->l2b_kva[l2pte_index(va)];
+		pt_entry_t *ptep = sptep;
 
 		while (va < next_bucket) {
-			pte = *ptep;
-			if (!l2pte_minidata(pte)) {
+			const pt_entry_t opte = *ptep;
+			if (!l2pte_minidata(opte)) {
 				cpu_dcache_wbinv_range(va, PAGE_SIZE);
 				cpu_tlb_flushD_SE(va);
-				*ptep = pte & ~L2_B;
+				l2pte_set(ptep, opte & ~L2_B, opte);
 			}
-			ptep++;
+			ptep += PAGE_SIZE / L2_S_SIZE;
 			va += PAGE_SIZE;
 		}
 		PTE_SYNC_RANGE(sptep, (u_int)(ptep - sptep));

Index: src/sys/arch/arm/include/arm32/pmap.h
diff -u src/sys/arch/arm/include/arm32/pmap.h:1.120 src/sys/arch/arm/include/arm32/pmap.h:1.121
--- src/sys/arch/arm/include/arm32/pmap.h:1.120	Wed Jun 12 21:34:12 2013
+++ src/sys/arch/arm/include/arm32/pmap.h	Wed Jul  3 21:37:35 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.120 2013/06/12 21:34:12 matt Exp $	*/
+/*	$NetBSD: pmap.h,v 1.121 2013/07/03 21:37:35 matt Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
@@ -451,6 +451,27 @@ pmap_ptesync(pt_entry_t *ptep, size_t cn
 				 (L2_B | L2_C | L2_XS_T_TEX(TEX_XSCALE_X)))\
 				 == (L2_C | L2_XS_T_TEX(TEX_XSCALE_X)))
 
+static inline void
+l2pte_set(pt_entry_t *ptep, pt_entry_t pte, pt_entry_t opte)
+{
+	KASSERT(*ptep == opte);
+	*ptep = pte;
+	for (vsize_t k = 1; k < PAGE_SIZE / L2_S_SIZE; k++) {
+		KASSERT(ptep[k] == opte ? opte + k * L2_S_SIZE : 0);
+		pte += L2_S_SIZE;
+		ptep[k] = pte;
+	}
+}       
+
+static inline void
+l2pte_reset(pt_entry_t *ptep)
+{
+	*ptep = 0;
+	for (vsize_t k = 1; k < PAGE_SIZE / L2_S_SIZE; k++) {
+		ptep[k] = 0;
+	}
+}       
+
 /* L1 and L2 page table macros */
 #define pmap_pde_v(pde)		l1pte_valid(*(pde))
 #define pmap_pde_section(pde)	l1pte_section_p(*(pde))

Reply via email to