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))