diff options
| author | scw <scw@NetBSD.org> | 2005-12-10 21:19:57 +0000 |
|---|---|---|
| committer | scw <scw@NetBSD.org> | 2005-12-10 21:19:57 +0000 |
| commit | 5536ecb20f52ab3fdbe23ef7893acf79ea39ebce (patch) | |
| tree | d9fa0fddf9c9188e8113c84035e4f956f5c437e3 /sys | |
| parent | 705000f60a74b9e2b4499c358303c201a6c8f294 (diff) | |
Implement pmap_collect() for arm32.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/arch/arm/arm32/pmap.c | 73 | ||||
| -rw-r--r-- | sys/arch/arm/include/arm32/pmap.h | 5 |
2 files changed, 44 insertions, 34 deletions
diff --git a/sys/arch/arm/arm32/pmap.c b/sys/arch/arm/arm32/pmap.c index 6918b83c357..39487f5c187 100644 --- a/sys/arch/arm/arm32/pmap.c +++ b/sys/arch/arm/arm32/pmap.c @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.155 2005/12/08 22:41:44 yamt Exp $ */ +/* $NetBSD: pmap.c,v 1.156 2005/12/10 21:19:57 scw Exp $ */ /* * Copyright 2003 Wasabi Systems, Inc. @@ -212,7 +212,7 @@ #include <machine/param.h> #include <arm/arm32/katelib.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.155 2005/12/08 22:41:44 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.156 2005/12/10 21:19:57 scw Exp $"); #ifdef PMAP_DEBUG @@ -489,7 +489,7 @@ static boolean_t pmap_is_cached(pmap_t); static void pmap_enter_pv(struct vm_page *, struct pv_entry *, pmap_t, vaddr_t, u_int); static struct pv_entry *pmap_find_pv(struct vm_page *, pmap_t, vaddr_t); -static struct pv_entry *pmap_remove_pv(struct vm_page *, pmap_t, vaddr_t); +static struct pv_entry *pmap_remove_pv(struct vm_page *, pmap_t, vaddr_t, int); static u_int pmap_modify_pv(struct vm_page *, pmap_t, vaddr_t, u_int, u_int); @@ -755,7 +755,7 @@ pmap_find_pv(struct vm_page *pg, pmap_t pm, vaddr_t va) * => we return the removed pve */ static struct pv_entry * -pmap_remove_pv(struct vm_page *pg, pmap_t pm, vaddr_t va) +pmap_remove_pv(struct vm_page *pg, pmap_t pm, vaddr_t va, int skip_wired) { struct pv_entry *pve, **prevptr; @@ -767,11 +767,14 @@ pmap_remove_pv(struct vm_page *pg, pmap_t pm, vaddr_t va) while (pve) { if (pve->pv_pmap == pm && pve->pv_va == va) { /* match? */ - NPDEBUG(PDB_PVDUMP, - printf("pmap_remove_pv: pm %p, pg %p, flags 0x%x\n", pm, pg, pve->pv_flags)); + NPDEBUG(PDB_PVDUMP, printf("pmap_remove_pv: pm %p, pg " + "%p, flags 0x%x\n", pm, pg, pve->pv_flags)); + if (pve->pv_flags & PVF_WIRED) { + if (skip_wired) + return (NULL); + --pm->pm_stats.wired_count; + } *prevptr = pve->pv_next; /* remove it! */ - if (pve->pv_flags & PVF_WIRED) - --pm->pm_stats.wired_count; if (pm == pmap_kernel()) { if (pve->pv_flags & PVF_WRITE) pg->mdpage.krw_mappings--; @@ -2069,7 +2072,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) * must remove it from the PV list */ simple_lock(&opg->mdpage.pvh_slock); - pve = pmap_remove_pv(opg, pm, va); + pve = pmap_remove_pv(opg, pm, va, 0); pmap_vac_me_harder(opg, pm, 0); simple_unlock(&opg->mdpage.pvh_slock); oflags = pve->pv_flags; @@ -2130,7 +2133,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) * at this address. */ simple_lock(&opg->mdpage.pvh_slock); - pve = pmap_remove_pv(opg, pm, va); + pve = pmap_remove_pv(opg, pm, va, 0); pmap_vac_me_harder(opg, pm, 0); simple_unlock(&opg->mdpage.pvh_slock); oflags = pve->pv_flags; @@ -2244,7 +2247,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) #define PMAP_REMOVE_CLEAN_LIST_SIZE 3 void -pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) +pmap_do_remove(pmap_t pm, vaddr_t sva, vaddr_t eva, int skip_wired) { struct l2_bucket *l2b; vaddr_t next_bucket; @@ -2256,8 +2259,8 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) } cleanlist[PMAP_REMOVE_CLEAN_LIST_SIZE]; u_int mappings, is_exec, is_refd; - NPDEBUG(PDB_REMOVE, printf("pmap_remove: pmap=%p sva=%08lx eva=%08lx\n", - pm, sva, eva)); + NPDEBUG(PDB_REMOVE, printf("pmap_do_remove: pmap=%p sva=%08lx " + "eva=%08lx\n", pm, sva, eva)); /* * we lock in the pmap => pv_head direction @@ -2289,9 +2292,8 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) } ptep = &l2b->l2b_kva[l2pte_index(sva)]; - mappings = 0; - while (sva < next_bucket) { + for (mappings = 0; sva < next_bucket; sva += PAGE_SIZE, ptep++){ struct vm_page *pg; pt_entry_t pte; paddr_t pa; @@ -2299,15 +2301,10 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) pte = *ptep; if (pte == 0) { - /* - * Nothing here, move along - */ - sva += PAGE_SIZE; - ptep++; + /* Nothing here, move along */ continue; } - pm->pm_stats.resident_count--; pa = l2pte_pa(pte); is_exec = 0; is_refd = 1; @@ -2320,7 +2317,7 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) if ((pg = PHYS_TO_VM_PAGE(pa)) != NULL) { struct pv_entry *pve; simple_lock(&pg->mdpage.pvh_slock); - pve = pmap_remove_pv(pg, pm, sva); + pve = pmap_remove_pv(pg, pm, sva, skip_wired); pmap_vac_me_harder(pg, pm, 0); simple_unlock(&pg->mdpage.pvh_slock); if (pve != NULL) { @@ -2331,15 +2328,27 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) PV_BEEN_REFD(pve->pv_flags); } pool_put(&pmap_pv_pool, pve); + } else + if (skip_wired) { + /* The mapping is wired. Skip it */ + continue; } + } else + if (skip_wired) { + /* Unmanaged pages are always wired. */ + continue; } + mappings++; + if (!l2pte_valid(pte)) { + /* + * 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; PTE_SYNC_CURRENT(pm, ptep); - sva += PAGE_SIZE; - ptep++; - mappings++; continue; } @@ -2378,10 +2387,6 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) pmap_tlb_flushD_SE(pm, sva); } } - - sva += PAGE_SIZE; - ptep++; - mappings++; } /* @@ -2423,6 +2428,7 @@ pmap_remove(pmap_t pm, vaddr_t sva, vaddr_t eva) } pmap_free_l2_bucket(pm, l2b, mappings); + pm->pm_stats.resident_count -= mappings; } pmap_release_pmap_lock(pm); @@ -2982,10 +2988,11 @@ out: void pmap_collect(pmap_t pm) { - /* - * Nothing to do. - * We don't even need to free-up the process' L1. - */ + + pmap_idcache_wbinv_all(pm); + pm->pm_remove_all = TRUE; + pmap_do_remove(pm, VM_MIN_ADDRESS, VM_MAX_ADDRESS, 1); + pmap_update(pm); } /* diff --git a/sys/arch/arm/include/arm32/pmap.h b/sys/arch/arm/include/arm32/pmap.h index f4a1f45c043..640be44b7c8 100644 --- a/sys/arch/arm/include/arm32/pmap.h +++ b/sys/arch/arm/include/arm32/pmap.h @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.77 2003/10/13 20:50:34 scw Exp $ */ +/* $NetBSD: pmap.h,v 1.78 2005/12/10 21:19:57 scw Exp $ */ /* * Copyright (c) 2002, 2003 Wasabi Systems, Inc. @@ -236,6 +236,8 @@ extern int pmap_debug_level; /* Only exists if PMAP_DEBUG */ #define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) #define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_remove(pmap,sva,eva) pmap_do_remove((pmap),(sva),(eva),0) + #define pmap_is_modified(pg) \ (((pg)->mdpage.pvh_attrs & PVF_MOD) != 0) #define pmap_is_referenced(pg) \ @@ -258,6 +260,7 @@ boolean_t pmap_extract(pmap_t, vaddr_t, paddr_t *); /* Functions we use internally. */ void pmap_bootstrap(pd_entry_t *, vaddr_t, vaddr_t); +void pmap_do_remove(pmap_t, vaddr_t, vaddr_t, int); int pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t, int); boolean_t pmap_get_pde_pte(pmap_t, vaddr_t, pd_entry_t **, pt_entry_t **); boolean_t pmap_get_pde(pmap_t, vaddr_t, pd_entry_t **); |
