diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-12-11 17:19:48 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-12-11 17:19:48 +0000 |
commit | fd8805df000b68f061013f444749f8d5e546c090 (patch) | |
tree | 9d51e7679d8d2520dbf695dc26c64c614b8c10ff /sys/powerpc/aim/mmu_oea64.c | |
parent | a17e44c25805a7b00f15693e883cac5f2135e432 (diff) | |
download | FreeBSD-src-fd8805df000b68f061013f444749f8d5e546c090.zip FreeBSD-src-fd8805df000b68f061013f444749f8d5e546c090.tar.gz |
Keep track of PVO entries in each pmap, which allows much faster
pmap_remove() for large sparse requests. This can prevent pmap_remove()
operations on 64-bit process destruction or swapout that would take
several hundred times the lifetime of the universe to complete. This
behavior is largely indistinguishable from a hang.
Diffstat (limited to 'sys/powerpc/aim/mmu_oea64.c')
-rw-r--r-- | sys/powerpc/aim/mmu_oea64.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index 7500462..4413780 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -831,6 +831,7 @@ moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) kernel_pmap->pmap_phys = kernel_pmap; CPU_FILL(&kernel_pmap->pm_active); + LIST_INIT(&kernel_pmap->pmap_pvo); PMAP_LOCK_INIT(kernel_pmap); @@ -1855,6 +1856,7 @@ void moea64_pinit(mmu_t mmu, pmap_t pmap) { PMAP_LOCK_INIT(pmap); + LIST_INIT(&pmap->pmap_pvo); pmap->pm_slb_tree_root = slb_alloc_tree(); pmap->pm_slb = slb_alloc_user_cache(); @@ -1868,6 +1870,7 @@ moea64_pinit(mmu_t mmu, pmap_t pmap) uint32_t hash; PMAP_LOCK_INIT(pmap); + LIST_INIT(&pmap->pmap_pvo); if (pmap_bootstrapped) pmap->pmap_phys = (pmap_t)moea64_kextract(mmu, @@ -2034,10 +2037,18 @@ moea64_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva) vm_page_lock_queues(); PMAP_LOCK(pm); - for (; sva < eva; sva += PAGE_SIZE) { - pvo = moea64_pvo_find_va(pm, sva); - if (pvo != NULL) + if ((eva - sva)/PAGE_SIZE < 10) { + for (; sva < eva; sva += PAGE_SIZE) { + pvo = moea64_pvo_find_va(pm, sva); + if (pvo != NULL) + moea64_pvo_remove(mmu, pvo); + } + } else { + LIST_FOREACH(pvo, &pm->pmap_pvo, pvo_plink) { + if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva) + continue; moea64_pvo_remove(mmu, pvo); + } } vm_page_unlock_queues(); PMAP_UNLOCK(pm); @@ -2231,6 +2242,11 @@ moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone, (uint64_t)(pa) | pte_lo, flags); /* + * Add to pmap list + */ + LIST_INSERT_HEAD(&pm->pmap_pvo, pvo, pvo_plink); + + /* * Remember if the list was empty and therefore will be the first * item. */ @@ -2311,9 +2327,10 @@ moea64_pvo_remove(mmu_t mmu, struct pvo_entry *pvo) } /* - * Remove this PVO from the PV list. + * Remove this PVO from the PV and pmap lists. */ LIST_REMOVE(pvo, pvo_vlink); + LIST_REMOVE(pvo, pvo_plink); /* * Remove this from the overflow list and return it to the pool |