summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-12-28 14:10:59 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-12-28 14:10:59 +0000
commita7bfdd02fe4106044791878771234737d19b306f (patch)
tree73c35da798331991dbcccc65af0baef51c4f9607 /sys/arch/mvme88k
parent81ff1af0e72f519a866334b95d0e977f78fa94ad (diff)
More optimizations borrowed from the m68k pmap:
- in loops over va space, do the empty segment test only once per segment - do not flush tlb for wiring-only changes While there: - in pmap_remove_all(), do not treat wired pages special. - move more paranoid tests from DIAGNOSTIC to DEBUG.
Diffstat (limited to 'sys/arch/mvme88k')
-rw-r--r--sys/arch/mvme88k/mvme88k/pmap.c213
1 files changed, 110 insertions, 103 deletions
diff --git a/sys/arch/mvme88k/mvme88k/pmap.c b/sys/arch/mvme88k/mvme88k/pmap.c
index 078d2d6c2b4..c91d3e62de0 100644
--- a/sys/arch/mvme88k/mvme88k/pmap.c
+++ b/sys/arch/mvme88k/mvme88k/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.98 2003/12/23 00:53:17 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.99 2003/12/28 14:10:58 miod Exp $ */
/*
* Copyright (c) 2001, 2002, 2003 Miodrag Vallat
* Copyright (c) 1998-2001 Steve Murphree, Jr.
@@ -343,7 +343,7 @@ pmap_pte(pmap_t pmap, vaddr_t virt)
{
sdt_entry_t *sdt;
-#ifdef DIAGNOSTIC
+#ifdef DEBUG
/*XXX will this change if physical memory is not contiguous? */
/* take a look at PDTIDX XXXnivas */
if (pmap == PMAP_NULL)
@@ -977,7 +977,7 @@ pmap_bootstrap(vaddr_t load_start, paddr_t *phys_start, paddr_t *phys_end,
virt = *virt_start;
SYSMAP(caddr_t, vmpte, vmmap, 1);
- *vmpte = PG_NV;
+ invalidate_pte(vmpte);
SYSMAP(struct msgbuf *, msgbufmap, msgbufp, btoc(MSGBUFSIZE));
@@ -1132,7 +1132,7 @@ pmap_zero_page(struct vm_page *pg)
*
* This routines allocates a pmap structure.
*/
-struct pmap *
+pmap_t
pmap_create(void)
{
pmap_t pmap;
@@ -1303,7 +1303,7 @@ pmap_destroy(pmap_t pmap)
{
int count;
-#ifdef DIAGNOSTIC
+#ifdef DEBUG
if (pmap == kernel_pmap)
panic("pmap_destroy: Attempt to destroy kernel pmap");
#endif
@@ -1495,7 +1495,7 @@ pmap_remove_pte(pmap_t pmap, vaddr_t va, pt_entry_t *pte)
void
pmap_remove_range(pmap_t pmap, vaddr_t s, vaddr_t e)
{
- vaddr_t va;
+ vaddr_t va, seva;
#ifdef DEBUG
if (pmap_con_dbg & CD_RM) {
@@ -1509,19 +1509,22 @@ pmap_remove_range(pmap_t pmap, vaddr_t s, vaddr_t e)
/*
* Loop through the range in vm_page_size increments.
*/
- for (va = s; va < e; va += PAGE_SIZE) {
+ for (va = s; va < e;) {
sdt_entry_t *sdt;
sdt = SDTENT(pmap, va);
+ seva = (va & SDT_MASK) + (1 << SDT_SHIFT);
/* If no segment table, skip a whole segment */
if (!SDT_VALID(sdt)) {
- va &= SDT_MASK;
- va += (1 << SDT_SHIFT) - PAGE_SIZE;
+ va = seva;
continue;
}
- pmap_remove_pte(pmap, va, pmap_pte(pmap, va));
+ if (seva > e)
+ seva = e;
+ for (; va < seva; va += PAGE_SIZE)
+ pmap_remove_pte(pmap, va, pmap_pte(pmap, va));
}
}
@@ -1642,26 +1645,16 @@ remove_all_Retry:
pte = pmap_pte(pmap, va);
if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) {
- pvl = pvl->pv_next;
- goto next; /* no page mapping */
- }
- if (pmap_pte_w(pte)) {
-#ifdef DEBUG
- if (pmap_con_dbg & CD_RMAL)
- printf("pmap_remove_all: wired mapping for %lx not removed\n",
- pg);
-#endif
- pvl = pvl->pv_next;
- goto next;
- }
+ pvl = pvl->pv_next; /* no page mapping */
+ } else {
+ pmap_remove_pte(pmap, va, pte);
- pmap_remove_pte(pmap, va, pte);
+ /*
+ * Do not free any page tables,
+ * leave that for when VM calls pmap_collect().
+ */
+ }
- /*
- * Do not free any page tables,
- * leaves that for when VM calls pmap_collect().
- */
-next:
simple_unlock(&pmap->pm_lock);
}
SPLX(spl);
@@ -1696,20 +1689,20 @@ pmap_protect(pmap_t pmap, vaddr_t s, vaddr_t e, vm_prot_t prot)
{
int spl;
pt_entry_t *pte, ap;
- vaddr_t va;
+ vaddr_t va, seva;
u_int users;
boolean_t kflush;
- if ((prot & VM_PROT_READ) == 0) {
- pmap_remove(pmap, s, e);
- return;
- }
-
#ifdef DIAGNOSTIC
- if (s > e)
+ if (s >= e)
panic("pmap_protect: start grater than end address");
#endif
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, s, e);
+ return;
+ }
+
ap = m88k_protection(pmap, prot) & PG_PROT;
PMAP_LOCK(pmap, spl);
@@ -1722,31 +1715,37 @@ pmap_protect(pmap_t pmap, vaddr_t s, vaddr_t e, vm_prot_t prot)
/*
* Loop through the range in vm_page_size increments.
*/
- for (va = s; va < e; va += PAGE_SIZE) {
+ for (va = s; va < e;) {
sdt_entry_t *sdt;
sdt = SDTENT(pmap, va);
+ seva = (va & SDT_MASK) + (1 << SDT_SHIFT);
/* If no segment table, skip a whole segment */
if (!SDT_VALID(sdt)) {
- va &= SDT_MASK;
- va += (1 << SDT_SHIFT) - PAGE_SIZE;
+ va = seva;
continue;
}
- pte = pmap_pte(pmap, va);
- if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) {
- continue; /* no page mapping */
- }
+ if (seva > e)
+ seva = e;
+ for (; va < seva; va += PAGE_SIZE) {
+ pte = pmap_pte(pmap, va);
+ if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) {
+ continue; /* no page mapping */
+ }
- /*
- * Invalidate pte temporarily to avoid the
- * modified bit and/or the reference bit being
- * written back by any other cpu.
- */
- *pte = (invalidate_pte(pte) & ~PG_PROT) | ap;
- flush_atc_entry(users, va, kflush);
- pte++;
+ if ((*pte & PG_PROT) ^ ap) {
+ /*
+ * Invalidate pte temporarily to avoid the
+ * modified bit and/or the reference bit being
+ * written back by any other cpu.
+ */
+ *pte = (invalidate_pte(pte) ^ PG_PROT);
+ flush_atc_entry(users, va, kflush);
+ }
+ pte++;
+ }
}
PMAP_UNLOCK(pmap, spl);
}
@@ -1921,7 +1920,7 @@ int
pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
{
int spl;
- pt_entry_t *pte, template;
+ pt_entry_t *pte, opte, template;
paddr_t old_pa;
pv_entry_t pv_e, pvl;
u_int users;
@@ -1965,25 +1964,23 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
/*
* Special case if the physical page is already mapped at this address.
*/
- old_pa = ptoa(PG_PFNUM(*pte));
+ opte = *pte;
+ old_pa = ptoa(PG_PFNUM(opte));
#ifdef DEBUG
if (pmap_con_dbg & CD_ENT)
- printf("(pmap_enter) old_pa %x pte %x\n", old_pa, *pte);
+ printf("(pmap_enter) old_pa %x pte %x\n", old_pa, opte);
#endif
if (old_pa == pa) {
/* May be changing its wired attributes or protection */
- if (wired && !(pmap_pte_w(pte)))
+ if (wired && !(pmap_pte_w(&opte)))
pmap->pm_stats.wired_count++;
- else if (!wired && pmap_pte_w(pte))
+ else if (!wired && pmap_pte_w(&opte))
pmap->pm_stats.wired_count--;
-
- pvl = NULL;
} else { /* if (pa == old_pa) */
- /* Remove old mapping from the PV list if necessary. */
- if (va >= phys_map_vaddr1 && va < phys_map_vaddr_end)
- flush_atc_entry(users, va, TRUE);
- else
- pmap_remove_pte(pmap, va, pte);
+ if (old_pa != NULL) {
+ if (va < phys_map_vaddr1 || va >= phys_map_vaddr_end)
+ pmap_remove_pte(pmap, va, pte);
+ }
pg = PHYS_TO_VM_PAGE(pa);
#ifdef DEBUG
@@ -1993,7 +1990,7 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
phys_map_vaddr1, phys_map_vaddr2, va, old_pa,
pg != NULL ? 1 : 0);
printf("pte %x pfn %x valid %x\n",
- pte, PG_PFNUM(*pte), PDT_VALID(pte));
+ pte, PG_PFNUM(opte), PDT_VALID(&opte));
}
}
#endif
@@ -2049,6 +2046,14 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
pv_e->pv_flags = 0;
pvl->pv_next = pv_e;
}
+
+ /*
+ * Cache attribute flags
+ */
+ if (flags & VM_PROT_WRITE)
+ pvl->pv_flags |= PG_U | PG_M;
+ else if (flags & VM_PROT_ALL)
+ pvl->pv_flags |= PG_U;
}
/*
@@ -2068,30 +2073,27 @@ pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
else
template |= CACHE_GLOBAL;
- if (flags & VM_PROT_WRITE)
- template |= PG_U | PG_M;
- else if (flags & VM_PROT_ALL)
- template |= PG_U;
-
+ template |= (opte & (PG_U | PG_M)) | pa;
/*
- * Invalidate pte temporarily to avoid being written
- * back the modified bit and/or the reference bit by
- * any other cpu.
+ * No need to flush anything if it's just a wiring change...
*/
- template |= invalidate_pte(pte) & (PG_U | PG_M);
- *pte = template | pa;
- flush_atc_entry(users, va, kflush);
+ if ((template ^ opte) == PG_W) {
+ *pte = template;
+ } else {
+ /*
+ * Invalidate pte temporarily to avoid being written
+ * back the modified bit and/or the reference bit by
+ * any other cpu.
+ */
+ invalidate_pte(pte);
+ *pte = template;
+ flush_atc_entry(users, va, kflush);
+ }
#ifdef DEBUG
if (pmap_con_dbg & CD_ENT)
- printf("(pmap_enter) set pte to %x\n", *pte);
+ printf("(pmap_enter) set pte to %x\n", template);
#endif
- /*
- * Cache attribute flags
- */
- if (pvl != NULL)
- pvl->pv_flags |= (template & (PG_U | PG_M));
-
PMAP_UNLOCK(pmap, spl);
return 0;
@@ -2120,11 +2122,14 @@ pmap_unwire(pmap_t pmap, vaddr_t v)
PMAP_LOCK(pmap, spl);
- if ((pte = pmap_pte(pmap, v)) == PT_ENTRY_NULL)
+ pte = pmap_pte(pmap, v);
+#ifdef DEBUG
+ if (pte == PT_ENTRY_NULL)
panic("pmap_unwire: pte missing");
+#endif
if (pmap_pte_w(pte)) {
- /* unwired mapping */
+ /* unwire mapping */
pmap->pm_stats.wired_count--;
*pte &= ~PG_W;
}
@@ -2169,7 +2174,7 @@ pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap)
int i;
#endif
-#ifdef DIAGNOSTIC
+#ifdef DEBUG
if (pmap == PMAP_NULL)
panic("pmap_extract: pmap is NULL");
#endif
@@ -2782,10 +2787,9 @@ pmap_is_referenced(struct vm_page *pg)
void
pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
{
- if (!(prot & VM_PROT_READ))
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE)
pmap_remove_all(pg);
- else if (!(prot & VM_PROT_WRITE))
- /* copy on write */
+ else if ((prot & VM_PROT_WRITE) == VM_PROT_NONE)
pmap_changebit(pg, PG_RO, ~0);
}
@@ -2845,7 +2849,7 @@ pmap_kremove(vaddr_t va, vsize_t len)
{
int spl;
u_int users;
- vaddr_t e;
+ vaddr_t e, seva;
#ifdef DEBUG
if (pmap_con_dbg & CD_RM)
@@ -2858,33 +2862,36 @@ pmap_kremove(vaddr_t va, vsize_t len)
PMAP_LOCK(kernel_pmap, spl);
users = kernel_pmap->pm_cpus;
- e = va + round_page(len);
- for (; va < e; va += PAGE_SIZE) {
+ for (e = va + len; va < e;) {
sdt_entry_t *sdt;
pt_entry_t *pte;
sdt = SDTENT(kernel_pmap, va);
+ seva = (va & SDT_MASK) + (1 << SDT_SHIFT);
/* If no segment table, skip a whole segment */
if (!SDT_VALID(sdt)) {
- va &= SDT_MASK;
- va += (1 << SDT_SHIFT) - PAGE_SIZE;
+ va = seva;
continue;
}
- pte = pmap_pte(kernel_pmap, va);
- if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) {
- continue; /* no page mapping */
- }
+ if (seva > e)
+ seva = e;
+ for (; va < seva; va += PAGE_SIZE) {
+ pte = pmap_pte(kernel_pmap, va);
+ if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) {
+ continue; /* no page mapping */
+ }
- /*
- * Update the counts
- */
- kernel_pmap->pm_stats.resident_count--;
- kernel_pmap->pm_stats.wired_count--;
+ /*
+ * Update the counts
+ */
+ kernel_pmap->pm_stats.resident_count--;
+ kernel_pmap->pm_stats.wired_count--;
- invalidate_pte(pte);
- flush_atc_entry(users, va, TRUE);
+ invalidate_pte(pte);
+ flush_atc_entry(users, va, TRUE);
+ }
}
PMAP_UNLOCK(map, spl);
}