Module Name: src
Committed By: skrll
Date: Wed Oct 29 22:52:21 UTC 2014
Modified Files:
src/sys/arch/arm/arm32: pmap.c
Log Message:
Apply a bunch of break-before-make, i.e. set PTEs to zero, flush the TLB
(across all CPUs) and set new PTE value. Mostly from matt@ with some
updates from me.
Flush the branch predictor in pmap_update.
To generate a diff of this commit:
cvs rdiff -u -r1.306 -r1.307 src/sys/arch/arm/arm32/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/arm/arm32/pmap.c
diff -u src/sys/arch/arm/arm32/pmap.c:1.306 src/sys/arch/arm/arm32/pmap.c:1.307
--- src/sys/arch/arm/arm32/pmap.c:1.306 Wed Oct 29 22:11:34 2014
+++ src/sys/arch/arm/arm32/pmap.c Wed Oct 29 22:52:21 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.306 2014/10/29 22:11:34 skrll Exp $ */
+/* $NetBSD: pmap.c,v 1.307 2014/10/29 22:52:21 skrll Exp $ */
/*
* Copyright 2003 Wasabi Systems, Inc.
@@ -215,7 +215,7 @@
#include <arm/locore.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.306 2014/10/29 22:11:34 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.307 2014/10/29 22:52:21 skrll Exp $");
//#define PMAP_DEBUG
#ifdef PMAP_DEBUG
@@ -2496,11 +2496,14 @@ pmap_clearbit(struct vm_page_md *md, pad
}
if (npte != opte) {
- l2pte_set(ptep, npte, opte);
+ l2pte_reset(ptep);
PTE_SYNC(ptep);
/* Flush the TLB entry if a current pmap. */
pmap_tlb_flush_SE(pm, va, oflags);
+
+ l2pte_set(ptep, npte, 0);
+ PTE_SYNC(ptep);
}
pmap_release_pmap_lock(pm);
@@ -2655,6 +2658,9 @@ pmap_syncicache_page(struct vm_page_md *
for (size_t i = 0, j = 0; i < way_size;
i += PAGE_SIZE, j += PAGE_SIZE / L2_S_SIZE) {
+ l2pte_reset(ptep + j);
+ PTE_SYNC(ptep + j);
+
pmap_tlb_flush_SE(kpm, dstp + i, PVF_REF | PVF_EXEC);
/*
* Set up a PTE with to flush these cache lines.
@@ -2883,10 +2889,6 @@ pmap_page_remove(struct vm_page_md *md,
pmap_release_page_lock(md);
pmap_acquire_pmap_lock(pm);
-#ifdef ARM_MMU_EXTENDED
- pmap_tlb_invalidate_addr(pm, pv->pv_va);
-#endif
-
l2b = pmap_get_l2_bucket(pm, pv->pv_va);
KASSERTMSG(l2b != NULL, "%#lx", pv->pv_va);
@@ -2908,7 +2910,14 @@ pmap_page_remove(struct vm_page_md *md,
*/
l2pte_reset(ptep);
PTE_SYNC_CURRENT(pm, ptep);
+
+#ifdef ARM_MMU_EXTENDED
+ /* XXXNH pmap_tlb_flush_SE()? */
+ pmap_tlb_invalidate_addr(pm, pv->pv_va);
+#endif
+
pmap_free_l2_bucket(pm, l2b, PAGE_SIZE / L2_S_SIZE);
+
pmap_release_pmap_lock(pm);
pool_put(&pmap_pv_pool, pv);
@@ -3307,8 +3316,11 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
* identical, so there's no need to update the page table.
*/
if (npte != opte) {
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
+ pmap_tlb_flush_SE(pm, va, oflags);
- l2pte_set(ptep, npte, opte);
+ l2pte_set(ptep, npte, 0);
PTE_SYNC(ptep);
#ifndef ARM_MMU_EXTENDED
bool is_cached = pmap_is_cached(pm);
@@ -3336,8 +3348,6 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
}
#endif /* !ARM_MMU_EXTENDED */
- pmap_tlb_flush_SE(pm, va, oflags);
-
#ifndef ARM_MMU_EXTENDED
UVMHIST_LOG(maphist, " is_cached %d cs 0x%08x\n",
is_cached, pm->pm_cstate.cs_all, 0, 0);
@@ -3481,6 +3491,7 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
*/
l2pte_reset(ptep);
PTE_SYNC_CURRENT(pm, ptep);
+ pmap_tlb_flush_SE(pm, sva, flags);
continue;
}
@@ -3488,7 +3499,7 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
if (pm == pmap_kernel()) {
l2pte_reset(ptep);
PTE_SYNC(ptep);
- pmap_tlb_flush_SE(pm, sva, flags);
+ pmap_tlb_flush_SE(pm, sva, flags);
continue;
}
#endif
@@ -3531,6 +3542,8 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
if (cleanlist_idx <= PMAP_REMOVE_CLEAN_LIST_SIZE) {
total += cleanlist_idx;
for (cnt = 0; cnt < cleanlist_idx; cnt++) {
+ l2pte_reset(cleanlist[cnt].ptep);
+ PTE_SYNC_CURRENT(pm, cleanlist[cnt].ptep);
#ifdef ARM_MMU_EXTENDED
vaddr_t clva = cleanlist[cnt].va;
pmap_tlb_flush_SE(pm, clva, PVF_REF);
@@ -3547,8 +3560,6 @@ pmap_remove(pmap_t pm, vaddr_t sva, vadd
PVF_REF | flags);
}
#endif /* ARM_MMU_EXTENDED */
- l2pte_reset(cleanlist[cnt].ptep);
- PTE_SYNC_CURRENT(pm, cleanlist[cnt].ptep);
}
/*
@@ -3682,6 +3693,8 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
}
#endif
if (l2pte_valid_p(opte)) {
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
#ifdef PMAP_CACHE_VIVT
cpu_dcache_wbinv_range(va, PAGE_SIZE);
#endif
@@ -3699,7 +3712,7 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
if (prot & VM_PROT_EXECUTE)
npte &= ~L2_XS_XN;
#endif
- l2pte_set(ptep, npte, opte);
+ l2pte_set(ptep, npte, 0);
PTE_SYNC(ptep);
if (pg) {
@@ -3790,7 +3803,8 @@ pmap_kremove(vaddr_t va, vsize_t len)
if (next_bucket > eva)
next_bucket = eva;
- struct l2_bucket * const l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ pmap_t kpm = pmap_kernel();
+ struct l2_bucket * const l2b = pmap_get_l2_bucket(kpm, va);
KDASSERT(l2b != NULL);
pt_entry_t * const sptep = &l2b->l2b_kva[l2pte_index(va)];
@@ -3825,13 +3839,13 @@ pmap_kremove(vaddr_t va, vsize_t len)
}
}
if (l2pte_valid_p(opte)) {
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
#ifdef PMAP_CACHE_VIVT
cpu_dcache_wbinv_range(va, PAGE_SIZE);
#endif
cpu_tlb_flushD_SE(va);
- }
- if (opte) {
- l2pte_reset(ptep);
+
mappings += PAGE_SIZE / L2_S_SIZE;
}
va += PAGE_SIZE;
@@ -3840,7 +3854,7 @@ pmap_kremove(vaddr_t va, vsize_t len)
KDASSERTMSG(mappings <= l2b->l2b_occupancy, "%u %u",
mappings, l2b->l2b_occupancy);
l2b->l2b_occupancy -= mappings;
- PTE_SYNC_RANGE(sptep, (u_int)(ptep - sptep));
+ //PTE_SYNC_RANGE(sptep, (u_int)(ptep - sptep));
#ifdef UVMHIST
total_mappings += mappings;
#endif
@@ -3939,9 +3953,11 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
pmap_acquire_pmap_lock(pm);
+#ifndef ARM_MMU_EXTENDED
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;
+#endif
+ u_int clr_mask = PVF_WRITE | ((prot & VM_PROT_EXECUTE) ? 0 : PVF_EXEC);
while (sva < eva) {
next_bucket = L2_NEXT_BUCKET_VA(sva);
@@ -3960,7 +3976,9 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
const pt_entry_t opte = *ptep;
if (l2pte_valid_p(opte) && l2pte_writable_p(opte)) {
struct vm_page *pg;
+#ifndef ARM_MMU_EXTENDED
u_int f;
+#endif
#ifdef PMAP_CACHE_VIVT
/*
@@ -3974,7 +3992,12 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
pg = PHYS_TO_VM_PAGE(l2pte_pa(opte));
pt_entry_t npte = l2pte_set_readonly(opte);
- l2pte_set(ptep, npte, opte);
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
+#ifdef ARM_MMU_EXTENDED
+ pmap_tlb_flush_SE(pm, sva, PVF_REF);
+#endif
+ l2pte_set(ptep, npte, 0);
PTE_SYNC(ptep);
if (pg != NULL) {
@@ -3982,10 +4005,14 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
paddr_t pa = VM_PAGE_TO_PHYS(pg);
pmap_acquire_page_lock(md);
- f = pmap_modify_pv(md, pa, pm, sva,
- clr_mask, 0);
+#ifndef ARM_MMU_EXTENDED
+ f =
+#endif
+ pmap_modify_pv(md, pa, pm, sva,
+ clr_mask, 0);
pmap_vac_me_harder(md, pa, pm, sva);
pmap_release_page_lock(md);
+#ifndef ARM_MMU_EXTENDED
} else {
f = PVF_REF | PVF_EXEC;
}
@@ -3994,6 +4021,7 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
flags |= f;
} else {
pmap_tlb_flush_SE(pm, sva, f);
+#endif
}
}
@@ -4002,6 +4030,7 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
}
}
+#ifndef ARM_MMU_EXTENDED
if (flush) {
if (PV_BEEN_EXECD(flags)) {
pmap_tlb_flushID(pm);
@@ -4009,6 +4038,7 @@ pmap_protect(pmap_t pm, vaddr_t sva, vad
pmap_tlb_flushD(pm);
}
}
+#endif
pmap_release_pmap_lock(pm);
}
@@ -4207,12 +4237,15 @@ pmap_prefetchabt_fixup(void *v)
KASSERT(pv != NULL);
if (PV_IS_EXEC_P(pv->pv_flags)) {
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
+ pmap_tlb_flush_SE(pm, va, PVF_EXEC | PVF_REF);
if (!PV_IS_EXEC_P(md->pvh_attrs)) {
pmap_syncicache_page(md, pa);
}
rv = ABORT_FIXUP_RETURN;
- l2pte_set(ptep, opte & ~L2_XS_XN, opte);
- pmap_tlb_flush_SE(pm, va, PVF_EXEC | PVF_REF);
+ l2pte_set(ptep, opte & ~L2_XS_XN, 0);
+ PTE_SYNC(ptep);
}
pmap_release_page_lock(md);
@@ -4358,7 +4391,11 @@ pmap_fault_fixup(pmap_t pm, vaddr_t va,
| (pm != pmap_kernel() ? L2_XS_nG : 0)
#endif
| 0;
- l2pte_set(ptep, npte, opte);
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
+ pmap_tlb_flush_SE(pm, va,
+ (ftype & VM_PROT_EXECUTE) ? PVF_EXEC | PVF_REF : PVF_REF);
+ l2pte_set(ptep, npte, 0);
PTE_SYNC(ptep);
PMAPCOUNT(fixup_mod);
rv = 1;
@@ -4425,7 +4462,11 @@ pmap_fault_fixup(pmap_t pm, vaddr_t va,
}
#endif /* ARM_MMU_EXTENDED */
pmap_release_page_lock(md);
- l2pte_set(ptep, npte, opte);
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
+ pmap_tlb_flush_SE(pm, va,
+ (ftype & VM_PROT_EXECUTE) ? PVF_EXEC | PVF_REF : PVF_REF);
+ l2pte_set(ptep, npte, 0);
PTE_SYNC(ptep);
PMAPCOUNT(fixup_ref);
rv = 1;
@@ -4463,7 +4504,10 @@ pmap_fault_fixup(pmap_t pm, vaddr_t va,
* Turn off no-execute.
*/
KASSERT(opte & L2_XS_nG);
- l2pte_set(ptep, opte & ~L2_XS_XN, opte);
+ l2pte_reset(ptep);
+ PTE_SYNC(ptep);
+ pmap_tlb_flush_SE(pm, va, PVF_EXEC | PVF_REF);
+ l2pte_set(ptep, opte & ~L2_XS_XN, 0);
PTE_SYNC(ptep);
rv = 1;
PMAPCOUNT(fixup_exec);
@@ -4611,9 +4655,6 @@ pmap_fault_fixup(pmap_t pm, vaddr_t va,
}
#endif
- pmap_tlb_flush_SE(pm, va,
- (ftype & VM_PROT_EXECUTE) ? PVF_EXEC | PVF_REF : PVF_REF);
-
rv = 1;
out:
@@ -4920,6 +4961,11 @@ pmap_update(pmap_t pm)
}
#ifdef ARM_MMU_EXTENDED
+#if defined(MULTIPROCESSOR)
+ armreg_bpiallis_write(0);
+#else
+ armreg_bpiall_write(0);
+#endif
#if defined(MULTIPROCESSOR) && PMAP_MAX_TLB > 1
u_int pending = atomic_swap_uint(&pmap->pm_shootdown_pending, 0);