summaryrefslogtreecommitdiff
path: root/sys/arch/hppa
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/hppa')
-rw-r--r--sys/arch/hppa/hppa/pmap.c85
1 files changed, 50 insertions, 35 deletions
diff --git a/sys/arch/hppa/hppa/pmap.c b/sys/arch/hppa/hppa/pmap.c
index 75eae16412f..effda061841 100644
--- a/sys/arch/hppa/hppa/pmap.c
+++ b/sys/arch/hppa/hppa/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.155 2010/05/24 15:04:55 deraadt Exp $ */
+/* $OpenBSD: pmap.c,v 1.156 2011/05/02 19:42:39 miod Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
@@ -116,6 +116,8 @@ void pmap_dump_pv(paddr_t pa);
int pmap_check_alias(struct pv_entry *pve, vaddr_t va,
pt_entry_t pte);
+#define IS_IOPAGE(pa) ((pa) >= HPPA_IOBEGIN)
+
struct vm_page *
pmap_pagealloc(struct uvm_object *obj, voff_t off)
{
@@ -355,10 +357,12 @@ pmap_dump_pv(paddr_t pa)
struct pv_entry *pve;
pg = PHYS_TO_VM_PAGE(pa);
- simple_lock(&pg->mdpage.pvh_lock);
- for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next)
- printf("%x:%lx\n", pve->pv_pmap->pm_space, pve->pv_va);
- simple_unlock(&pg->mdpage.pvh_lock);
+ if (pg != NULL) {
+ simple_lock(&pg->mdpage.pvh_lock);
+ for (pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next)
+ printf("%x:%lx\n", pve->pv_pmap->pm_space, pve->pv_va);
+ simple_unlock(&pg->mdpage.pvh_lock);
+ }
}
#endif
@@ -698,37 +702,35 @@ pmap_destroy(pmap)
#ifdef DIAGNOSTIC
while ((pg = RB_ROOT(&pmap->pm_obj.memt))) {
pt_entry_t *pde, *epde;
- struct vm_page *sheep;
- struct pv_entry *haggis;
-
- if (pg == pmap->pm_pdir_pg)
- continue;
+ struct vm_page *spg;
+ struct pv_entry *pv, *npv;
+ KASSERT(pg != pmap->pm_pdir_pg);
+ pa = VM_PAGE_TO_PHYS(pg);
#ifdef PMAPDEBUG
- printf("pmap_destroy(%p): stray ptp 0x%lx w/ %d ents:",
- pmap, VM_PAGE_TO_PHYS(pg), pg->wire_count - 1);
+ printf("pmap_destroy(%p): stray ptp 0x%lx w/ %u ents:",
+ pmap, pa, pg->wire_count - 1);
#endif
- pde = (pt_entry_t *)VM_PAGE_TO_PHYS(pg);
- epde = (pt_entry_t *)(VM_PAGE_TO_PHYS(pg) + PAGE_SIZE);
+ pde = (pt_entry_t *)pa;
+ epde = (pt_entry_t *)(pa + PAGE_SIZE);
for (; pde < epde; pde++) {
if (*pde == 0)
continue;
- sheep = PHYS_TO_VM_PAGE(PTE_PAGE(*pde));
- for (haggis = sheep->mdpage.pvh_list; haggis != NULL; )
- if (haggis->pv_pmap == pmap) {
+ spg = PHYS_TO_VM_PAGE(PTE_PAGE(*pde));
+ if (spg == NULL)
+ continue;
+ for (pv = spg->mdpage.pvh_list; pv != NULL; pv = npv) {
+ npv = pv->pv_next;
+ if (pv->pv_pmap == pmap) {
#ifdef PMAPDEBUG
printf(" 0x%x", haggis->pv_va);
#endif
- pmap_remove(pmap, haggis->pv_va,
- haggis->pv_va + PAGE_SIZE);
-
- /* exploit the sacred knowledge
- of lambeous ozzmosis */
- haggis = sheep->mdpage.pvh_list;
- } else
- haggis = haggis->pv_next;
+ pmap_remove(pmap, pv->pv_va,
+ pv->pv_va + PAGE_SIZE);
+ }
+ }
}
#ifdef PMAPDEBUG
printf("\n");
@@ -819,9 +821,12 @@ pmap_enter(pmap, va, pa, prot, flags)
}
pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
- simple_lock(&pg->mdpage.pvh_lock);
- pve = pmap_pv_remove(pg, pmap, va);
- pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
+ if (pg != NULL) {
+ simple_lock(&pg->mdpage.pvh_lock);
+ pve = pmap_pv_remove(pg, pmap, va);
+ pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
+ simple_unlock(&pg->mdpage.pvh_lock);
+ }
} else {
DPRINTF(PDB_ENTER,
("pmap_enter: new mapping 0x%x -> 0x%x\n", va, pa));
@@ -832,7 +837,6 @@ pmap_enter(pmap, va, pa, prot, flags)
pmap->pm_stats.wired_count++;
if (ptp)
ptp->wire_count++;
- simple_lock(&pg->mdpage.pvh_lock);
}
if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pa)))) {
@@ -845,17 +849,20 @@ pmap_enter(pmap, va, pa, prot, flags)
panic("pmap_enter: no pv entries available");
}
pte |= PTE_PROT(pmap_prot(pmap, prot));
+ simple_lock(&pg->mdpage.pvh_lock);
if (pmap_check_alias(pg->mdpage.pvh_list, va, pte))
pmap_page_remove(pg);
pmap_pv_enter(pg, pve, pmap, va, ptp);
+ simple_unlock(&pg->mdpage.pvh_lock);
} else if (pve)
pmap_pv_free(pve);
- simple_unlock(&pg->mdpage.pvh_lock);
enter:
/* preserve old ref & mod */
pte = pa | PTE_PROT(pmap_prot(pmap, prot)) |
(pte & PTE_PROT(TLB_UNCACHABLE|TLB_DIRTY|TLB_REFTRAP));
+ if (IS_IOPAGE(pa))
+ pte |= PTE_PROT(TLB_UNCACHABLE);
if (wired)
pte |= PTE_PROT(TLB_WIRED);
pmap_pte_set(pde, va, pte);
@@ -876,7 +883,7 @@ pmap_remove(pmap, sva, eva)
struct pv_entry *pve;
volatile pt_entry_t *pde;
pt_entry_t pte;
- struct vm_page *pg;
+ struct vm_page *pg, *ptp;
vaddr_t pdemask;
int batch;
@@ -921,6 +928,12 @@ pmap_remove(pmap, sva, eva)
if ((pve = pmap_pv_remove(pg, pmap, sva)))
pmap_pv_free(pve);
simple_unlock(&pg->mdpage.pvh_lock);
+ } else {
+ if (IS_IOPAGE(PTE_PAGE(pte))) {
+ ptp = pmap_pde_ptp(pmap, pde);
+ if (ptp != NULL)
+ pmap_pde_release(pmap, sva, ptp);
+ }
}
}
}
@@ -971,9 +984,11 @@ pmap_write_protect(pmap, sva, eva, prot)
continue;
pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
- simple_lock(&pg->mdpage.pvh_lock);
- pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
- simple_unlock(&pg->mdpage.pvh_lock);
+ if (pg != NULL) {
+ simple_lock(&pg->mdpage.pvh_lock);
+ pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
+ simple_unlock(&pg->mdpage.pvh_lock);
+ }
pmap_pte_flush(pmap, sva, pte);
pte &= ~PTE_PROT(TLB_AR_MASK);
@@ -1226,7 +1241,7 @@ pmap_kenter_pa(va, pa, prot)
opte = pmap_pte_get(pde, va);
pte = pa | PTE_PROT(TLB_WIRED | TLB_REFTRAP |
pmap_prot(pmap_kernel(), prot));
- if (pa >= HPPA_IOBEGIN)
+ if (IS_IOPAGE(pa))
pte |= PTE_PROT(TLB_UNCACHABLE);
if (opte)
pmap_pte_flush(pmap_kernel(), va, opte);