diff options
-rw-r--r-- | sys/amd64/amd64/pmap.c | 262 | ||||
-rw-r--r-- | sys/amd64/include/vmparam.h | 7 | ||||
-rw-r--r-- | sys/fs/specfs/spec_vnops.c | 7 | ||||
-rw-r--r-- | sys/i386/i386/pmap.c | 262 | ||||
-rw-r--r-- | sys/i386/include/vmparam.h | 7 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 60 | ||||
-rw-r--r-- | sys/kern/kern_malloc.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_subr.c | 5 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 11 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 11 | ||||
-rw-r--r-- | sys/miscfs/specfs/spec_vnops.c | 7 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_readwrite.c | 85 | ||||
-rw-r--r-- | sys/vm/vm_glue.c | 6 | ||||
-rw-r--r-- | sys/vm/vm_kern.c | 10 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 76 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 31 | ||||
-rw-r--r-- | sys/vm/vm_object.h | 3 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 113 | ||||
-rw-r--r-- | sys/vm/vm_page.h | 12 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 11 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 15 |
21 files changed, 572 insertions, 433 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index c12a276..8a4bf2e 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -39,7 +39,7 @@ * SUCH DAMAGE. * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 - * $Id: pmap.c,v 1.180 1998/02/03 22:09:01 bde Exp $ + * $Id: pmap.c,v 1.181 1998/02/04 22:32:10 eivind Exp $ */ /* @@ -215,7 +215,6 @@ static vm_page_t pmap_allocpte __P((pmap_t pmap, vm_offset_t va)); static int pmap_release_free_page __P((pmap_t pmap, vm_page_t p)); static vm_page_t _pmap_allocpte __P((pmap_t pmap, unsigned ptepindex)); static unsigned * pmap_pte_quick __P((pmap_t pmap, vm_offset_t va)); -static vm_page_t pmap_page_alloc __P((vm_object_t object, vm_pindex_t pindex)); static vm_page_t pmap_page_lookup __P((vm_object_t object, vm_pindex_t pindex)); static int pmap_unuse_pt __P((pmap_t, vm_offset_t, vm_page_t)); vm_offset_t pmap_kmem_choose(vm_offset_t addr) ; @@ -819,19 +818,6 @@ pmap_kremove(va) } static vm_page_t -pmap_page_alloc(object, pindex) - vm_object_t object; - vm_pindex_t pindex; -{ - vm_page_t m; - m = vm_page_alloc(object, pindex, VM_ALLOC_ZERO); - if (m == NULL) { - VM_WAIT; - } - return m; -} - -static vm_page_t pmap_page_lookup(object, pindex) vm_object_t object; vm_pindex_t pindex; @@ -876,8 +862,10 @@ pmap_new_proc(p) if ((up = p->p_addr) == NULL) { up = (struct user *) kmem_alloc_pageable(kernel_map, UPAGES * PAGE_SIZE); +#if !defined(MAX_PERF) if (up == NULL) panic("pmap_new_proc: u_map allocation failed"); +#endif p->p_addr = up; } @@ -888,10 +876,7 @@ pmap_new_proc(p) /* * Get a kernel stack page */ - while ((m = vm_page_alloc(upobj, - i, VM_ALLOC_NORMAL)) == NULL) { - VM_WAIT; - } + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); /* * Wire the page @@ -912,8 +897,9 @@ pmap_new_proc(p) } } - m->flags &= ~(PG_ZERO|PG_BUSY); - m->flags |= PG_MAPPED|PG_WRITEABLE; + PAGE_WAKEUP(m); + m->flags &= ~PG_ZERO; + m->flags |= PG_MAPPED | PG_WRITEABLE; m->valid = VM_PAGE_BITS_ALL; } if (updateneeded) @@ -940,6 +926,7 @@ pmap_dispose_proc(p) if ((m = vm_page_lookup(upobj, i)) == NULL) panic("pmap_dispose_proc: upage already missing???"); + m->flags |= PG_BUSY; oldpte = *(ptek + i); @@ -950,7 +937,7 @@ pmap_dispose_proc(p) vm_page_free(m); } - if (cpu_class < CPUCLASS_586) + if (cpu_class <= CPUCLASS_386) invltlb(); } @@ -986,43 +973,31 @@ void pmap_swapin_proc(p) struct proc *p; { - int i; + int i,rv; vm_object_t upobj; vm_page_t m; upobj = p->p_upages_obj; for(i=0;i<UPAGES;i++) { - int s; - s = splvm(); -retry: - if ((m = vm_page_lookup(upobj, i)) == NULL) { - if ((m = vm_page_alloc(upobj, i, VM_ALLOC_NORMAL)) == NULL) { - VM_WAIT; - goto retry; - } - } else { - if ((m->flags & PG_BUSY) || m->busy) { - m->flags |= PG_WANTED; - tsleep(m, PVM, "swinuw",0); - goto retry; - } - m->flags |= PG_BUSY; - } - vm_page_wire(m); - splx(s); + + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m)); if (m->valid != VM_PAGE_BITS_ALL) { - int rv; rv = vm_pager_get_pages(upobj, &m, 1, 0); +#if !defined(MAX_PERF) if (rv != VM_PAGER_OK) panic("pmap_swapin_proc: cannot get upages for proc: %d\n", p->p_pid); +#endif + m = vm_page_lookup(upobj, i); m->valid = VM_PAGE_BITS_ALL; } + + vm_page_wire(m); PAGE_WAKEUP(m); - m->flags |= PG_MAPPED|PG_WRITEABLE; + m->flags |= PG_MAPPED | PG_WRITEABLE; } } @@ -1175,9 +1150,8 @@ pmap_pinit(pmap) * allocate the page directory page */ retry: - ptdpg = pmap_page_alloc( pmap->pm_pteobj, PTDPTDI); - if (ptdpg == NULL) - goto retry; + ptdpg = vm_page_grab( pmap->pm_pteobj, PTDPTDI, + VM_ALLOC_NORMAL | VM_ALLOC_RETRY); ptdpg->wire_count = 1; ++cnt.v_wire_count; @@ -1224,10 +1198,8 @@ pmap_release_free_page(pmap, p) return 0; } - if (p->flags & PG_WANTED) { - p->flags &= ~PG_WANTED; - wakeup(p); - } + p->flags |= PG_BUSY; + splx(s); /* * Remove the page table page from the processes address space. @@ -1235,9 +1207,11 @@ pmap_release_free_page(pmap, p) pde[p->pindex] = 0; pmap->pm_stats.resident_count--; +#if !defined(MAX_PERF) if (p->hold_count) { panic("pmap_release: freeing held page table page"); } +#endif /* * Page directory pages need to have the kernel * stuff cleared, so they can go into the zero queue also. @@ -1254,9 +1228,7 @@ pmap_release_free_page(pmap, p) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) pmap->pm_ptphint = NULL; - p->flags |= PG_BUSY; vm_page_free_zero(p); - splx(s); return 1; } @@ -1271,28 +1243,12 @@ _pmap_allocpte(pmap, ptepindex) { vm_offset_t pteva, ptepa; vm_page_t m; - int needszero = 0; /* * Find or fabricate a new pagetable page */ -retry: - m = vm_page_lookup(pmap->pm_pteobj, ptepindex); - if (m == NULL) { - m = pmap_page_alloc(pmap->pm_pteobj, ptepindex); - if (m == NULL) - goto retry; - if ((m->flags & PG_ZERO) == 0) - needszero = 1; - m->flags &= ~(PG_ZERO|PG_BUSY); - m->valid = VM_PAGE_BITS_ALL; - } else { - if ((m->flags & PG_BUSY) || m->busy) { - m->flags |= PG_WANTED; - tsleep(m, PVM, "ptewai", 0); - goto retry; - } - } + m = vm_page_grab(pmap->pm_pteobj, ptepindex, + VM_ALLOC_ZERO | VM_ALLOC_RETRY); if (m->queue != PQ_NONE) { int s = splvm(); @@ -1318,7 +1274,8 @@ retry: pmap->pm_stats.resident_count++; ptepa = VM_PAGE_TO_PHYS(m); - pmap->pm_pdir[ptepindex] = (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V); + pmap->pm_pdir[ptepindex] = + (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V | PG_A); /* * Set the page table hint @@ -1329,7 +1286,7 @@ retry: * Try to use the new mapping, but if we cannot, then * do it with the routine that maps the page explicitly. */ - if (needszero) { + if ((m->flags & PG_ZERO) == 0) { if ((((unsigned)pmap->pm_pdir[PTDPTDI]) & PG_FRAME) == (((unsigned) PTDpde) & PG_FRAME)) { pteva = UPT_MIN_ADDRESS + i386_ptob(ptepindex); @@ -1340,6 +1297,7 @@ retry: } m->valid = VM_PAGE_BITS_ALL; + m->flags &= ~(PG_ZERO|PG_BUSY); m->flags |= PG_MAPPED; return m; @@ -1480,10 +1438,11 @@ pmap_growkernel(vm_offset_t addr) /* * This index is bogus, but out of the way */ - nkpg = vm_page_alloc(kernel_object, - ptpidx, VM_ALLOC_SYSTEM); + nkpg = vm_page_alloc(kernel_object, ptpidx, VM_ALLOC_SYSTEM); +#if !defined(MAX_PERF) if (!nkpg) panic("pmap_growkernel: no memory to grow kernel"); +#endif vm_page_wire(nkpg); vm_page_remove(nkpg); @@ -1528,7 +1487,9 @@ pmap_destroy(pmap) count = --pmap->pm_count; if (count == 0) { pmap_release(pmap); +#if !defined(MAX_PERF) panic("destroying a pmap is not yet implemented"); +#endif } } @@ -1648,12 +1609,12 @@ pmap_remove_entry(pmap, ppv, va) rtval = 0; if (pv) { + rtval = pmap_unuse_pt(pmap, va, pv->pv_ptem); TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); ppv->pv_list_count--; - if (TAILQ_FIRST(&ppv->pv_list) == NULL) { - ppv->pv_vm_page->flags &= ~(PG_MAPPED|PG_WRITEABLE); - } + if (TAILQ_FIRST(&ppv->pv_list) == NULL) + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist); free_pv_entry(pv); @@ -1728,6 +1689,8 @@ pmap_remove_pte(pmap, ptq, va) if (pmap_track_modified(va)) ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; } + if (oldpte & PG_A) + ppv->pv_vm_page->flags |= PG_REFERENCED; return pmap_remove_entry(pmap, ppv, va); } else { return pmap_unuse_pt(pmap, va, NULL); @@ -1910,6 +1873,10 @@ pmap_remove_all(pa) *pte = 0; if (tpte & PG_W) pv->pv_pmap->pm_stats.wired_count--; + + if (tpte & PG_A) + ppv->pv_vm_page->flags |= PG_REFERENCED; + /* * Update the vm_page_t clean and reference bits. */ @@ -1934,11 +1901,12 @@ pmap_remove_all(pa) pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); free_pv_entry(pv); } - ppv->pv_vm_page->flags &= ~(PG_MAPPED|PG_WRITEABLE); + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); if (update_needed) invltlb(); + splx(s); return; } @@ -1951,9 +1919,8 @@ void pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) { register unsigned *ptbase; - vm_offset_t pdnxt; - vm_offset_t ptpaddr; - vm_offset_t sindex, eindex; + vm_offset_t pdnxt, ptpaddr; + vm_pindex_t sindex, eindex; int anychanged; @@ -1965,6 +1932,9 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) return; } + if (prot & VM_PROT_WRITE) + return; + anychanged = 0; ptbase = get_ptbase(pmap); @@ -1999,27 +1969,32 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) for (; sindex != pdnxt; sindex++) { - unsigned pbits = ptbase[sindex]; + unsigned pbits; + pv_table_t *ppv; - if (prot & VM_PROT_WRITE) { - if ((pbits & (PG_RW|PG_V)) == PG_V) { - if (pbits & PG_MANAGED) { - vm_page_t m = PHYS_TO_VM_PAGE(pbits); - m->flags |= PG_WRITEABLE; - m->object->flags |= OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY; - } - ptbase[sindex] = pbits | PG_RW; - anychanged = 1; + pbits = ptbase[sindex]; + + if (pbits & PG_MANAGED) { + ppv = NULL; + if (pbits & PG_A) { + ppv = pa_to_pvh(pbits); + ppv->pv_vm_page->flags |= PG_REFERENCED; + pbits &= ~PG_A; } - } else if (pbits & PG_RW) { if (pbits & PG_M) { - vm_offset_t sva1 = i386_ptob(sindex); - if ((pbits & PG_MANAGED) && pmap_track_modified(sva1)) { - vm_page_t m = PHYS_TO_VM_PAGE(pbits); - m->dirty = VM_PAGE_BITS_ALL; + if (pmap_track_modified(i386_ptob(sindex))) { + if (ppv == NULL) + ppv = pa_to_pvh(pbits); + ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; + pbits &= ~PG_M; } } - ptbase[sindex] = pbits & ~(PG_M|PG_RW); + } + + pbits &= ~PG_RW; + + if (pbits != ptbase[sindex]) { + ptbase[sindex] = pbits; anychanged = 1; } } @@ -2089,6 +2064,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, #endif pte = pmap_pte(pmap, va); + +#if !defined(MAX_PERF) /* * Page Directory table entry not valid, we need a new PT page */ @@ -2096,12 +2073,16 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, panic("pmap_enter: invalid page directory, pdir=%p, va=0x%lx\n", pmap->pm_pdir[PTDPTDI], va); } +#endif origpte = *(vm_offset_t *)pte; pa &= PG_FRAME; opa = origpte & PG_FRAME; + +#if !defined(MAX_PERF) if (origpte & PG_PS) panic("pmap_enter: attempted pmap_enter on 4MB page"); +#endif /* * Mapping has not changed, must be protection or wiring change. @@ -2125,23 +2106,31 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, #endif /* + * Remove extra pte reference + */ + if (mpte) + mpte->hold_count--; + + if ((prot & VM_PROT_WRITE) && (origpte & PG_V)) { + if ((origpte & PG_RW) == 0) { + *pte |= PG_RW; + invltlb_1pg(va); + } + return; + } + + /* * We might be turning off write access to the page, * so we go ahead and sense modify status. */ if (origpte & PG_MANAGED) { - vm_page_t m; - if (origpte & PG_M) { - if (pmap_track_modified(va)) { - m = PHYS_TO_VM_PAGE(pa); - m->dirty = VM_PAGE_BITS_ALL; - } + if ((origpte & PG_M) && pmap_track_modified(va)) { + pv_table_t *ppv; + ppv = pa_to_pvh(opa); + ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; } pa |= PG_MANAGED; } - - if (mpte) - mpte->hold_count--; - goto validate; } /* @@ -2151,8 +2140,10 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, if (opa) { int err; err = pmap_remove_pte(pmap, pte, va); +#if !defined(MAX_PERF) if (err) panic("pmap_enter: pte vanished, va: 0x%x", va); +#endif } /* @@ -2242,8 +2233,10 @@ retry: * the hold count, and activate it. */ if (ptepa) { +#if !defined(MAX_PERF) if (ptepa & PG_PS) panic("pmap_enter_quick: unexpected mapping into 4MB page"); +#endif if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; @@ -2498,6 +2491,9 @@ pmap_prefault(pmap, addra, entry) unsigned *pte; addr = addra + pmap_prefault_pageorder[i]; + if (addr > addra + (PFFOR * PAGE_SIZE)) + addr = 0; + if (addr < starta || addr >= entry->end) continue; @@ -2614,8 +2610,10 @@ pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) vm_offset_t srcptepaddr; unsigned ptepindex; +#if !defined(MAX_PERF) if (addr >= UPT_MIN_ADDRESS) panic("pmap_copy: invalid to pmap_copy page tables\n"); +#endif pdnxt = ((addr + PAGE_SIZE*NPTEPG) & ~(PAGE_SIZE*NPTEPG - 1)); ptepindex = addr >> PDRSHIFT; @@ -2661,7 +2659,7 @@ pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) * accessed (referenced) bits * during the copy. */ - *dst_pte = ptetemp & ~(PG_M|PG_A); + *dst_pte = ptetemp & ~(PG_M | PG_A); dst_pmap->pm_stats.resident_count++; pmap_insert_entry(dst_pmap, addr, dstmpte, @@ -2701,10 +2699,12 @@ pmap_zero_page(phys) vm_offset_t phys; { #ifdef SMP +#if !defined(MAX_PERF) if (*(int *) prv_CMAP3) panic("pmap_zero_page: prv_CMAP3 busy"); +#endif - *(int *) prv_CMAP3 = PG_V | PG_RW | (phys & PG_FRAME); + *(int *) prv_CMAP3 = PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; invltlb_1pg((vm_offset_t) &prv_CPAGE3); bzero(&prv_CPAGE3, PAGE_SIZE); @@ -2712,10 +2712,12 @@ pmap_zero_page(phys) *(int *) prv_CMAP3 = 0; invltlb_1pg((vm_offset_t) &prv_CPAGE3); #else +#if !defined(MAX_PERF) if (*(int *) CMAP2) panic("pmap_zero_page: CMAP busy"); +#endif - *(int *) CMAP2 = PG_V | PG_RW | (phys & PG_FRAME); + *(int *) CMAP2 = PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; bzero(CADDR2, PAGE_SIZE); *(int *) CMAP2 = 0; invltlb_1pg((vm_offset_t) CADDR2); @@ -2734,13 +2736,15 @@ pmap_copy_page(src, dst) vm_offset_t dst; { #ifdef SMP +#if !defined(MAX_PERF) if (*(int *) prv_CMAP1) panic("pmap_copy_page: prv_CMAP1 busy"); if (*(int *) prv_CMAP2) panic("pmap_copy_page: prv_CMAP2 busy"); +#endif - *(int *) prv_CMAP1 = PG_V | PG_RW | (src & PG_FRAME); - *(int *) prv_CMAP2 = PG_V | PG_RW | (dst & PG_FRAME); + *(int *) prv_CMAP1 = PG_V | (src & PG_FRAME) | PG_A; + *(int *) prv_CMAP2 = PG_V | PG_RW | (dst & PG_FRAME) | PG_A | PG_M; invltlb_2pg( (vm_offset_t) &prv_CPAGE1, (vm_offset_t) &prv_CPAGE2); @@ -2750,11 +2754,13 @@ pmap_copy_page(src, dst) *(int *) prv_CMAP2 = 0; invltlb_2pg( (vm_offset_t) &prv_CPAGE1, (vm_offset_t) &prv_CPAGE2); #else +#if !defined(MAX_PERF) if (*(int *) CMAP1 || *(int *) CMAP2) panic("pmap_copy_page: CMAP busy"); +#endif - *(int *) CMAP1 = PG_V | PG_RW | (src & PG_FRAME); - *(int *) CMAP2 = PG_V | PG_RW | (dst & PG_FRAME); + *(int *) CMAP1 = PG_V | (src & PG_FRAME) | PG_A; + *(int *) CMAP2 = PG_V | PG_RW | (dst & PG_FRAME) | PG_A | PG_M; bcopy(CADDR1, CADDR2, PAGE_SIZE); @@ -2891,7 +2897,7 @@ pmap_remove_pages(pmap, sva, eva) ppv->pv_list_count--; TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); if (TAILQ_FIRST(&ppv->pv_list) == NULL) { - ppv->pv_vm_page->flags &= ~(PG_MAPPED|PG_WRITEABLE); + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); } pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); @@ -3082,6 +3088,7 @@ pmap_ts_referenced(vm_offset_t pa) for (pv = TAILQ_FIRST(&ppv->pv_list); pv; pv = TAILQ_NEXT(pv, pv_list)) { + /* * if the bit being tested is the modified bit, then * mark clean_map and ptes as never @@ -3094,11 +3101,15 @@ pmap_ts_referenced(vm_offset_t pa) if (pte == NULL) { continue; } + if (*pte & PG_A) { rtval++; *pte &= ~PG_A; + if (rtval > 16) + break; } } + splx(s); if (rtval) { invltlb(); @@ -3187,8 +3198,10 @@ pmap_mapdev(pa, size) size = roundup(size, PAGE_SIZE); va = kmem_alloc_pageable(kernel_map, size); +#if !defined(MAX_PERF) if (!va) panic("pmap_mapdev: Couldn't alloc kernel virtual memory"); +#endif pa = pa & PG_FRAME; for (tmpva = va; size > 0;) { @@ -3213,6 +3226,7 @@ pmap_mincore(pmap, addr) { unsigned *ptep, pte; + vm_page_t m; int val = 0; ptep = pmap_pte(pmap, addr); @@ -3221,10 +3235,18 @@ pmap_mincore(pmap, addr) } if (pte = *ptep) { + pv_table_t *ppv; vm_offset_t pa; + val = MINCORE_INCORE; + if ((pte & PG_MANAGED) == 0) + return val; + pa = pte & PG_FRAME; + ppv = pa_to_pvh((pa & PG_FRAME)); + m = ppv->pv_vm_page; + /* * Modified by us */ @@ -3233,22 +3255,20 @@ pmap_mincore(pmap, addr) /* * Modified by someone */ - else if (PHYS_TO_VM_PAGE(pa)->dirty || - pmap_is_modified(pa)) + else if (m->dirty || pmap_is_modified(pa)) val |= MINCORE_MODIFIED_OTHER; /* * Referenced by us */ - if (pte & PG_U) + if (pte & PG_A) val |= MINCORE_REFERENCED|MINCORE_REFERENCED_OTHER; /* * Referenced by someone */ - else if ((PHYS_TO_VM_PAGE(pa)->flags & PG_REFERENCED) || - pmap_ts_referenced(pa)) { + else if ((m->flags & PG_REFERENCED) || pmap_ts_referenced(pa)) { val |= MINCORE_REFERENCED_OTHER; - PHYS_TO_VM_PAGE(pa)->flags |= PG_REFERENCED; + m->flags |= PG_REFERENCED; } } return val; diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h index e8759b3..0764850 100644 --- a/sys/amd64/include/vmparam.h +++ b/sys/amd64/include/vmparam.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 - * $Id: vmparam.h,v 1.26 1997/06/25 20:18:58 tegge Exp $ + * $Id: vmparam.h,v 1.27 1997/10/27 00:38:46 jkh Exp $ */ @@ -120,4 +120,9 @@ #define VM_KMEM_SIZE (32 * 1024 * 1024) #endif +/* initial pagein size of beginning of executable file */ +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 +#endif + #endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c index 9d27a4c..ebeea74 100644 --- a/sys/fs/specfs/spec_vnops.c +++ b/sys/fs/specfs/spec_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 - * $Id: spec_vnops.c,v 1.53 1998/01/06 05:21:23 dyson Exp $ + * $Id: spec_vnops.c,v 1.54 1998/02/04 22:32:51 eivind Exp $ */ #include "opt_diagnostic.h" @@ -837,7 +837,10 @@ spec_getpages(ap) * now tell them that it is ok to use. */ if (!error) { - vm_page_deactivate(ap->a_m[i]); + if (ap->a_m[i]->flags & PG_WANTED) + vm_page_activate(ap->a_m[i]); + else + vm_page_deactivate(ap->a_m[i]); PAGE_WAKEUP(ap->a_m[i]); } else vnode_pager_freepage(ap->a_m[i]); diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index c12a276..8a4bf2e 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -39,7 +39,7 @@ * SUCH DAMAGE. * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 - * $Id: pmap.c,v 1.180 1998/02/03 22:09:01 bde Exp $ + * $Id: pmap.c,v 1.181 1998/02/04 22:32:10 eivind Exp $ */ /* @@ -215,7 +215,6 @@ static vm_page_t pmap_allocpte __P((pmap_t pmap, vm_offset_t va)); static int pmap_release_free_page __P((pmap_t pmap, vm_page_t p)); static vm_page_t _pmap_allocpte __P((pmap_t pmap, unsigned ptepindex)); static unsigned * pmap_pte_quick __P((pmap_t pmap, vm_offset_t va)); -static vm_page_t pmap_page_alloc __P((vm_object_t object, vm_pindex_t pindex)); static vm_page_t pmap_page_lookup __P((vm_object_t object, vm_pindex_t pindex)); static int pmap_unuse_pt __P((pmap_t, vm_offset_t, vm_page_t)); vm_offset_t pmap_kmem_choose(vm_offset_t addr) ; @@ -819,19 +818,6 @@ pmap_kremove(va) } static vm_page_t -pmap_page_alloc(object, pindex) - vm_object_t object; - vm_pindex_t pindex; -{ - vm_page_t m; - m = vm_page_alloc(object, pindex, VM_ALLOC_ZERO); - if (m == NULL) { - VM_WAIT; - } - return m; -} - -static vm_page_t pmap_page_lookup(object, pindex) vm_object_t object; vm_pindex_t pindex; @@ -876,8 +862,10 @@ pmap_new_proc(p) if ((up = p->p_addr) == NULL) { up = (struct user *) kmem_alloc_pageable(kernel_map, UPAGES * PAGE_SIZE); +#if !defined(MAX_PERF) if (up == NULL) panic("pmap_new_proc: u_map allocation failed"); +#endif p->p_addr = up; } @@ -888,10 +876,7 @@ pmap_new_proc(p) /* * Get a kernel stack page */ - while ((m = vm_page_alloc(upobj, - i, VM_ALLOC_NORMAL)) == NULL) { - VM_WAIT; - } + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); /* * Wire the page @@ -912,8 +897,9 @@ pmap_new_proc(p) } } - m->flags &= ~(PG_ZERO|PG_BUSY); - m->flags |= PG_MAPPED|PG_WRITEABLE; + PAGE_WAKEUP(m); + m->flags &= ~PG_ZERO; + m->flags |= PG_MAPPED | PG_WRITEABLE; m->valid = VM_PAGE_BITS_ALL; } if (updateneeded) @@ -940,6 +926,7 @@ pmap_dispose_proc(p) if ((m = vm_page_lookup(upobj, i)) == NULL) panic("pmap_dispose_proc: upage already missing???"); + m->flags |= PG_BUSY; oldpte = *(ptek + i); @@ -950,7 +937,7 @@ pmap_dispose_proc(p) vm_page_free(m); } - if (cpu_class < CPUCLASS_586) + if (cpu_class <= CPUCLASS_386) invltlb(); } @@ -986,43 +973,31 @@ void pmap_swapin_proc(p) struct proc *p; { - int i; + int i,rv; vm_object_t upobj; vm_page_t m; upobj = p->p_upages_obj; for(i=0;i<UPAGES;i++) { - int s; - s = splvm(); -retry: - if ((m = vm_page_lookup(upobj, i)) == NULL) { - if ((m = vm_page_alloc(upobj, i, VM_ALLOC_NORMAL)) == NULL) { - VM_WAIT; - goto retry; - } - } else { - if ((m->flags & PG_BUSY) || m->busy) { - m->flags |= PG_WANTED; - tsleep(m, PVM, "swinuw",0); - goto retry; - } - m->flags |= PG_BUSY; - } - vm_page_wire(m); - splx(s); + + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m)); if (m->valid != VM_PAGE_BITS_ALL) { - int rv; rv = vm_pager_get_pages(upobj, &m, 1, 0); +#if !defined(MAX_PERF) if (rv != VM_PAGER_OK) panic("pmap_swapin_proc: cannot get upages for proc: %d\n", p->p_pid); +#endif + m = vm_page_lookup(upobj, i); m->valid = VM_PAGE_BITS_ALL; } + + vm_page_wire(m); PAGE_WAKEUP(m); - m->flags |= PG_MAPPED|PG_WRITEABLE; + m->flags |= PG_MAPPED | PG_WRITEABLE; } } @@ -1175,9 +1150,8 @@ pmap_pinit(pmap) * allocate the page directory page */ retry: - ptdpg = pmap_page_alloc( pmap->pm_pteobj, PTDPTDI); - if (ptdpg == NULL) - goto retry; + ptdpg = vm_page_grab( pmap->pm_pteobj, PTDPTDI, + VM_ALLOC_NORMAL | VM_ALLOC_RETRY); ptdpg->wire_count = 1; ++cnt.v_wire_count; @@ -1224,10 +1198,8 @@ pmap_release_free_page(pmap, p) return 0; } - if (p->flags & PG_WANTED) { - p->flags &= ~PG_WANTED; - wakeup(p); - } + p->flags |= PG_BUSY; + splx(s); /* * Remove the page table page from the processes address space. @@ -1235,9 +1207,11 @@ pmap_release_free_page(pmap, p) pde[p->pindex] = 0; pmap->pm_stats.resident_count--; +#if !defined(MAX_PERF) if (p->hold_count) { panic("pmap_release: freeing held page table page"); } +#endif /* * Page directory pages need to have the kernel * stuff cleared, so they can go into the zero queue also. @@ -1254,9 +1228,7 @@ pmap_release_free_page(pmap, p) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) pmap->pm_ptphint = NULL; - p->flags |= PG_BUSY; vm_page_free_zero(p); - splx(s); return 1; } @@ -1271,28 +1243,12 @@ _pmap_allocpte(pmap, ptepindex) { vm_offset_t pteva, ptepa; vm_page_t m; - int needszero = 0; /* * Find or fabricate a new pagetable page */ -retry: - m = vm_page_lookup(pmap->pm_pteobj, ptepindex); - if (m == NULL) { - m = pmap_page_alloc(pmap->pm_pteobj, ptepindex); - if (m == NULL) - goto retry; - if ((m->flags & PG_ZERO) == 0) - needszero = 1; - m->flags &= ~(PG_ZERO|PG_BUSY); - m->valid = VM_PAGE_BITS_ALL; - } else { - if ((m->flags & PG_BUSY) || m->busy) { - m->flags |= PG_WANTED; - tsleep(m, PVM, "ptewai", 0); - goto retry; - } - } + m = vm_page_grab(pmap->pm_pteobj, ptepindex, + VM_ALLOC_ZERO | VM_ALLOC_RETRY); if (m->queue != PQ_NONE) { int s = splvm(); @@ -1318,7 +1274,8 @@ retry: pmap->pm_stats.resident_count++; ptepa = VM_PAGE_TO_PHYS(m); - pmap->pm_pdir[ptepindex] = (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V); + pmap->pm_pdir[ptepindex] = + (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V | PG_A); /* * Set the page table hint @@ -1329,7 +1286,7 @@ retry: * Try to use the new mapping, but if we cannot, then * do it with the routine that maps the page explicitly. */ - if (needszero) { + if ((m->flags & PG_ZERO) == 0) { if ((((unsigned)pmap->pm_pdir[PTDPTDI]) & PG_FRAME) == (((unsigned) PTDpde) & PG_FRAME)) { pteva = UPT_MIN_ADDRESS + i386_ptob(ptepindex); @@ -1340,6 +1297,7 @@ retry: } m->valid = VM_PAGE_BITS_ALL; + m->flags &= ~(PG_ZERO|PG_BUSY); m->flags |= PG_MAPPED; return m; @@ -1480,10 +1438,11 @@ pmap_growkernel(vm_offset_t addr) /* * This index is bogus, but out of the way */ - nkpg = vm_page_alloc(kernel_object, - ptpidx, VM_ALLOC_SYSTEM); + nkpg = vm_page_alloc(kernel_object, ptpidx, VM_ALLOC_SYSTEM); +#if !defined(MAX_PERF) if (!nkpg) panic("pmap_growkernel: no memory to grow kernel"); +#endif vm_page_wire(nkpg); vm_page_remove(nkpg); @@ -1528,7 +1487,9 @@ pmap_destroy(pmap) count = --pmap->pm_count; if (count == 0) { pmap_release(pmap); +#if !defined(MAX_PERF) panic("destroying a pmap is not yet implemented"); +#endif } } @@ -1648,12 +1609,12 @@ pmap_remove_entry(pmap, ppv, va) rtval = 0; if (pv) { + rtval = pmap_unuse_pt(pmap, va, pv->pv_ptem); TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); ppv->pv_list_count--; - if (TAILQ_FIRST(&ppv->pv_list) == NULL) { - ppv->pv_vm_page->flags &= ~(PG_MAPPED|PG_WRITEABLE); - } + if (TAILQ_FIRST(&ppv->pv_list) == NULL) + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist); free_pv_entry(pv); @@ -1728,6 +1689,8 @@ pmap_remove_pte(pmap, ptq, va) if (pmap_track_modified(va)) ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; } + if (oldpte & PG_A) + ppv->pv_vm_page->flags |= PG_REFERENCED; return pmap_remove_entry(pmap, ppv, va); } else { return pmap_unuse_pt(pmap, va, NULL); @@ -1910,6 +1873,10 @@ pmap_remove_all(pa) *pte = 0; if (tpte & PG_W) pv->pv_pmap->pm_stats.wired_count--; + + if (tpte & PG_A) + ppv->pv_vm_page->flags |= PG_REFERENCED; + /* * Update the vm_page_t clean and reference bits. */ @@ -1934,11 +1901,12 @@ pmap_remove_all(pa) pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); free_pv_entry(pv); } - ppv->pv_vm_page->flags &= ~(PG_MAPPED|PG_WRITEABLE); + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); if (update_needed) invltlb(); + splx(s); return; } @@ -1951,9 +1919,8 @@ void pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) { register unsigned *ptbase; - vm_offset_t pdnxt; - vm_offset_t ptpaddr; - vm_offset_t sindex, eindex; + vm_offset_t pdnxt, ptpaddr; + vm_pindex_t sindex, eindex; int anychanged; @@ -1965,6 +1932,9 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) return; } + if (prot & VM_PROT_WRITE) + return; + anychanged = 0; ptbase = get_ptbase(pmap); @@ -1999,27 +1969,32 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) for (; sindex != pdnxt; sindex++) { - unsigned pbits = ptbase[sindex]; + unsigned pbits; + pv_table_t *ppv; - if (prot & VM_PROT_WRITE) { - if ((pbits & (PG_RW|PG_V)) == PG_V) { - if (pbits & PG_MANAGED) { - vm_page_t m = PHYS_TO_VM_PAGE(pbits); - m->flags |= PG_WRITEABLE; - m->object->flags |= OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY; - } - ptbase[sindex] = pbits | PG_RW; - anychanged = 1; + pbits = ptbase[sindex]; + + if (pbits & PG_MANAGED) { + ppv = NULL; + if (pbits & PG_A) { + ppv = pa_to_pvh(pbits); + ppv->pv_vm_page->flags |= PG_REFERENCED; + pbits &= ~PG_A; } - } else if (pbits & PG_RW) { if (pbits & PG_M) { - vm_offset_t sva1 = i386_ptob(sindex); - if ((pbits & PG_MANAGED) && pmap_track_modified(sva1)) { - vm_page_t m = PHYS_TO_VM_PAGE(pbits); - m->dirty = VM_PAGE_BITS_ALL; + if (pmap_track_modified(i386_ptob(sindex))) { + if (ppv == NULL) + ppv = pa_to_pvh(pbits); + ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; + pbits &= ~PG_M; } } - ptbase[sindex] = pbits & ~(PG_M|PG_RW); + } + + pbits &= ~PG_RW; + + if (pbits != ptbase[sindex]) { + ptbase[sindex] = pbits; anychanged = 1; } } @@ -2089,6 +2064,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, #endif pte = pmap_pte(pmap, va); + +#if !defined(MAX_PERF) /* * Page Directory table entry not valid, we need a new PT page */ @@ -2096,12 +2073,16 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, panic("pmap_enter: invalid page directory, pdir=%p, va=0x%lx\n", pmap->pm_pdir[PTDPTDI], va); } +#endif origpte = *(vm_offset_t *)pte; pa &= PG_FRAME; opa = origpte & PG_FRAME; + +#if !defined(MAX_PERF) if (origpte & PG_PS) panic("pmap_enter: attempted pmap_enter on 4MB page"); +#endif /* * Mapping has not changed, must be protection or wiring change. @@ -2125,23 +2106,31 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, #endif /* + * Remove extra pte reference + */ + if (mpte) + mpte->hold_count--; + + if ((prot & VM_PROT_WRITE) && (origpte & PG_V)) { + if ((origpte & PG_RW) == 0) { + *pte |= PG_RW; + invltlb_1pg(va); + } + return; + } + + /* * We might be turning off write access to the page, * so we go ahead and sense modify status. */ if (origpte & PG_MANAGED) { - vm_page_t m; - if (origpte & PG_M) { - if (pmap_track_modified(va)) { - m = PHYS_TO_VM_PAGE(pa); - m->dirty = VM_PAGE_BITS_ALL; - } + if ((origpte & PG_M) && pmap_track_modified(va)) { + pv_table_t *ppv; + ppv = pa_to_pvh(opa); + ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; } pa |= PG_MANAGED; } - - if (mpte) - mpte->hold_count--; - goto validate; } /* @@ -2151,8 +2140,10 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, if (opa) { int err; err = pmap_remove_pte(pmap, pte, va); +#if !defined(MAX_PERF) if (err) panic("pmap_enter: pte vanished, va: 0x%x", va); +#endif } /* @@ -2242,8 +2233,10 @@ retry: * the hold count, and activate it. */ if (ptepa) { +#if !defined(MAX_PERF) if (ptepa & PG_PS) panic("pmap_enter_quick: unexpected mapping into 4MB page"); +#endif if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; @@ -2498,6 +2491,9 @@ pmap_prefault(pmap, addra, entry) unsigned *pte; addr = addra + pmap_prefault_pageorder[i]; + if (addr > addra + (PFFOR * PAGE_SIZE)) + addr = 0; + if (addr < starta || addr >= entry->end) continue; @@ -2614,8 +2610,10 @@ pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) vm_offset_t srcptepaddr; unsigned ptepindex; +#if !defined(MAX_PERF) if (addr >= UPT_MIN_ADDRESS) panic("pmap_copy: invalid to pmap_copy page tables\n"); +#endif pdnxt = ((addr + PAGE_SIZE*NPTEPG) & ~(PAGE_SIZE*NPTEPG - 1)); ptepindex = addr >> PDRSHIFT; @@ -2661,7 +2659,7 @@ pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) * accessed (referenced) bits * during the copy. */ - *dst_pte = ptetemp & ~(PG_M|PG_A); + *dst_pte = ptetemp & ~(PG_M | PG_A); dst_pmap->pm_stats.resident_count++; pmap_insert_entry(dst_pmap, addr, dstmpte, @@ -2701,10 +2699,12 @@ pmap_zero_page(phys) vm_offset_t phys; { #ifdef SMP +#if !defined(MAX_PERF) if (*(int *) prv_CMAP3) panic("pmap_zero_page: prv_CMAP3 busy"); +#endif - *(int *) prv_CMAP3 = PG_V | PG_RW | (phys & PG_FRAME); + *(int *) prv_CMAP3 = PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; invltlb_1pg((vm_offset_t) &prv_CPAGE3); bzero(&prv_CPAGE3, PAGE_SIZE); @@ -2712,10 +2712,12 @@ pmap_zero_page(phys) *(int *) prv_CMAP3 = 0; invltlb_1pg((vm_offset_t) &prv_CPAGE3); #else +#if !defined(MAX_PERF) if (*(int *) CMAP2) panic("pmap_zero_page: CMAP busy"); +#endif - *(int *) CMAP2 = PG_V | PG_RW | (phys & PG_FRAME); + *(int *) CMAP2 = PG_V | PG_RW | (phys & PG_FRAME) | PG_A | PG_M; bzero(CADDR2, PAGE_SIZE); *(int *) CMAP2 = 0; invltlb_1pg((vm_offset_t) CADDR2); @@ -2734,13 +2736,15 @@ pmap_copy_page(src, dst) vm_offset_t dst; { #ifdef SMP +#if !defined(MAX_PERF) if (*(int *) prv_CMAP1) panic("pmap_copy_page: prv_CMAP1 busy"); if (*(int *) prv_CMAP2) panic("pmap_copy_page: prv_CMAP2 busy"); +#endif - *(int *) prv_CMAP1 = PG_V | PG_RW | (src & PG_FRAME); - *(int *) prv_CMAP2 = PG_V | PG_RW | (dst & PG_FRAME); + *(int *) prv_CMAP1 = PG_V | (src & PG_FRAME) | PG_A; + *(int *) prv_CMAP2 = PG_V | PG_RW | (dst & PG_FRAME) | PG_A | PG_M; invltlb_2pg( (vm_offset_t) &prv_CPAGE1, (vm_offset_t) &prv_CPAGE2); @@ -2750,11 +2754,13 @@ pmap_copy_page(src, dst) *(int *) prv_CMAP2 = 0; invltlb_2pg( (vm_offset_t) &prv_CPAGE1, (vm_offset_t) &prv_CPAGE2); #else +#if !defined(MAX_PERF) if (*(int *) CMAP1 || *(int *) CMAP2) panic("pmap_copy_page: CMAP busy"); +#endif - *(int *) CMAP1 = PG_V | PG_RW | (src & PG_FRAME); - *(int *) CMAP2 = PG_V | PG_RW | (dst & PG_FRAME); + *(int *) CMAP1 = PG_V | (src & PG_FRAME) | PG_A; + *(int *) CMAP2 = PG_V | PG_RW | (dst & PG_FRAME) | PG_A | PG_M; bcopy(CADDR1, CADDR2, PAGE_SIZE); @@ -2891,7 +2897,7 @@ pmap_remove_pages(pmap, sva, eva) ppv->pv_list_count--; TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); if (TAILQ_FIRST(&ppv->pv_list) == NULL) { - ppv->pv_vm_page->flags &= ~(PG_MAPPED|PG_WRITEABLE); + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); } pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); @@ -3082,6 +3088,7 @@ pmap_ts_referenced(vm_offset_t pa) for (pv = TAILQ_FIRST(&ppv->pv_list); pv; pv = TAILQ_NEXT(pv, pv_list)) { + /* * if the bit being tested is the modified bit, then * mark clean_map and ptes as never @@ -3094,11 +3101,15 @@ pmap_ts_referenced(vm_offset_t pa) if (pte == NULL) { continue; } + if (*pte & PG_A) { rtval++; *pte &= ~PG_A; + if (rtval > 16) + break; } } + splx(s); if (rtval) { invltlb(); @@ -3187,8 +3198,10 @@ pmap_mapdev(pa, size) size = roundup(size, PAGE_SIZE); va = kmem_alloc_pageable(kernel_map, size); +#if !defined(MAX_PERF) if (!va) panic("pmap_mapdev: Couldn't alloc kernel virtual memory"); +#endif pa = pa & PG_FRAME; for (tmpva = va; size > 0;) { @@ -3213,6 +3226,7 @@ pmap_mincore(pmap, addr) { unsigned *ptep, pte; + vm_page_t m; int val = 0; ptep = pmap_pte(pmap, addr); @@ -3221,10 +3235,18 @@ pmap_mincore(pmap, addr) } if (pte = *ptep) { + pv_table_t *ppv; vm_offset_t pa; + val = MINCORE_INCORE; + if ((pte & PG_MANAGED) == 0) + return val; + pa = pte & PG_FRAME; + ppv = pa_to_pvh((pa & PG_FRAME)); + m = ppv->pv_vm_page; + /* * Modified by us */ @@ -3233,22 +3255,20 @@ pmap_mincore(pmap, addr) /* * Modified by someone */ - else if (PHYS_TO_VM_PAGE(pa)->dirty || - pmap_is_modified(pa)) + else if (m->dirty || pmap_is_modified(pa)) val |= MINCORE_MODIFIED_OTHER; /* * Referenced by us */ - if (pte & PG_U) + if (pte & PG_A) val |= MINCORE_REFERENCED|MINCORE_REFERENCED_OTHER; /* * Referenced by someone */ - else if ((PHYS_TO_VM_PAGE(pa)->flags & PG_REFERENCED) || - pmap_ts_referenced(pa)) { + else if ((m->flags & PG_REFERENCED) || pmap_ts_referenced(pa)) { val |= MINCORE_REFERENCED_OTHER; - PHYS_TO_VM_PAGE(pa)->flags |= PG_REFERENCED; + m->flags |= PG_REFERENCED; } } return val; diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h index e8759b3..0764850 100644 --- a/sys/i386/include/vmparam.h +++ b/sys/i386/include/vmparam.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 - * $Id: vmparam.h,v 1.26 1997/06/25 20:18:58 tegge Exp $ + * $Id: vmparam.h,v 1.27 1997/10/27 00:38:46 jkh Exp $ */ @@ -120,4 +120,9 @@ #define VM_KMEM_SIZE (32 * 1024 * 1024) #endif +/* initial pagein size of beginning of executable file */ +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 +#endif + #endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index cc62bc3..4d40448 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_exec.c,v 1.74 1998/01/11 21:35:38 dyson Exp $ + * $Id: kern_exec.c,v 1.75 1998/02/04 22:32:31 eivind Exp $ */ #include "opt_diagnostic.h" @@ -359,8 +359,9 @@ int exec_map_first_page(imgp) struct image_params *imgp; { - int s; - vm_page_t m; + int s, rv, i; + int initial_pagein; + vm_page_t ma[VM_INITIAL_PAGEIN]; vm_object_t object; @@ -371,40 +372,45 @@ exec_map_first_page(imgp) object = imgp->vp->v_object; s = splvm(); -retry: - m = vm_page_lookup(object, 0); - if (m == NULL) { - m = vm_page_alloc(object, 0, VM_ALLOC_NORMAL); - if (m == NULL) { - VM_WAIT; - goto retry; + ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + + if ((ma[0]->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) { + initial_pagein = VM_INITIAL_PAGEIN; + if (initial_pagein > object->size) + initial_pagein = object->size; + for (i = 1; i < initial_pagein; i++) { + if (ma[i] = vm_page_lookup(object, i)) { + if ((ma[i]->flags & PG_BUSY) || ma[i]->busy) + break; + if (ma[i]->valid) + break; + ma[i]->flags |= PG_BUSY; + } else { + ma[i] = vm_page_alloc(object, i, VM_ALLOC_NORMAL); + if (ma[i] == NULL) + break; + } } - } else if ((m->flags & PG_BUSY) || m->busy) { - m->flags |= PG_WANTED; - tsleep(m, PVM, "execpw", 0); - goto retry; - } + initial_pagein = i; - m->flags |= PG_BUSY; + rv = vm_pager_get_pages(object, ma, initial_pagein, 0); + ma[0] = vm_page_lookup(object, 0); - if ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) { - int rv; - rv = vm_pager_get_pages(object, &m, 1, 0); - if (rv != VM_PAGER_OK) { - vm_page_protect(m, VM_PROT_NONE); - vm_page_deactivate(m); - PAGE_WAKEUP(m); + if ((rv != VM_PAGER_OK) || (ma[0] == NULL)) { + vm_page_protect(ma[0], VM_PROT_NONE); + vm_page_deactivate(ma[0]); + PAGE_WAKEUP(ma[0]); splx(s); return EIO; } } - vm_page_wire(m); - PAGE_WAKEUP(m); + vm_page_wire(ma[0]); + PAGE_WAKEUP(ma[0]); splx(s); - pmap_kenter((vm_offset_t) imgp->image_header, VM_PAGE_TO_PHYS(m)); - imgp->firstpage = m; + pmap_kenter((vm_offset_t) imgp->image_header, VM_PAGE_TO_PHYS(ma[0])); + imgp->firstpage = ma[0]; return 0; } diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index cf23124..bba797f 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 - * $Id: kern_malloc.c,v 1.39 1998/01/22 17:29:47 dyson Exp $ + * $Id: kern_malloc.c,v 1.40 1998/02/04 22:32:32 eivind Exp $ */ #include "opt_diagnostic.h" @@ -197,7 +197,7 @@ malloc(size, type, flags) kbp->kb_next = ((struct freelist *)va)->next; #ifdef DIAGNOSTIC freep = (struct freelist *)va; - savedtype = type->ks_shortdesc; + savedtype = (char *) type->ks_shortdesc; #if BYTE_ORDER == BIG_ENDIAN freep->type = (struct malloc_type *)WEIRD_ADDR >> 16; #endif diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index d762ac4..7037a2d 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 - * $Id: kern_subr.c,v 1.16 1998/01/22 17:29:49 dyson Exp $ + * $Id: kern_subr.c,v 1.17 1998/02/04 22:32:34 eivind Exp $ */ #include "opt_diagnostic.h" @@ -193,8 +193,9 @@ uioread(n, uio, obj, nread) int error; *nread = 0; - if (vfs_ioopt > 1) + if (vfs_ioopt < 2) return 0; + error = 0; while (n > 0 && uio->uio_resid) { diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 958bd71..08b65bc 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.127 1998/01/31 01:17:58 tegge Exp $ + * $Id: vfs_subr.c,v 1.128 1998/02/04 22:32:40 eivind Exp $ */ /* @@ -1170,6 +1170,7 @@ vclean(vp, flags, p) struct proc *p; { int active; + vm_object_t obj; /* * Check to see if the vnode is in use. If so we have to reference it @@ -1199,18 +1200,18 @@ vclean(vp, flags, p) * Clean out any buffers associated with the vnode. */ vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); - if (vp->v_object) { - if (vp->v_object->ref_count == 0) { + if (obj = vp->v_object) { + if (obj->ref_count == 0) { /* * This is a normal way of shutting down the object/vnode * association. */ - vm_object_terminate(vp->v_object); + vm_object_terminate(obj); } else { /* * Woe to the process that tries to page now :-). */ - vm_pager_deallocate(vp->v_object); + vm_pager_deallocate(obj); } } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 958bd71..08b65bc 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.127 1998/01/31 01:17:58 tegge Exp $ + * $Id: vfs_subr.c,v 1.128 1998/02/04 22:32:40 eivind Exp $ */ /* @@ -1170,6 +1170,7 @@ vclean(vp, flags, p) struct proc *p; { int active; + vm_object_t obj; /* * Check to see if the vnode is in use. If so we have to reference it @@ -1199,18 +1200,18 @@ vclean(vp, flags, p) * Clean out any buffers associated with the vnode. */ vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); - if (vp->v_object) { - if (vp->v_object->ref_count == 0) { + if (obj = vp->v_object) { + if (obj->ref_count == 0) { /* * This is a normal way of shutting down the object/vnode * association. */ - vm_object_terminate(vp->v_object); + vm_object_terminate(obj); } else { /* * Woe to the process that tries to page now :-). */ - vm_pager_deallocate(vp->v_object); + vm_pager_deallocate(obj); } } diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c index 9d27a4c..ebeea74 100644 --- a/sys/miscfs/specfs/spec_vnops.c +++ b/sys/miscfs/specfs/spec_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 - * $Id: spec_vnops.c,v 1.53 1998/01/06 05:21:23 dyson Exp $ + * $Id: spec_vnops.c,v 1.54 1998/02/04 22:32:51 eivind Exp $ */ #include "opt_diagnostic.h" @@ -837,7 +837,10 @@ spec_getpages(ap) * now tell them that it is ok to use. */ if (!error) { - vm_page_deactivate(ap->a_m[i]); + if (ap->a_m[i]->flags & PG_WANTED) + vm_page_activate(ap->a_m[i]); + else + vm_page_deactivate(ap->a_m[i]); PAGE_WAKEUP(ap->a_m[i]); } else vnode_pager_freepage(ap->a_m[i]); diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index 395d6bd..3996692 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95 - * $Id: ufs_readwrite.c,v 1.40 1998/01/22 17:30:22 dyson Exp $ + * $Id: ufs_readwrite.c,v 1.41 1998/01/30 11:34:05 phk Exp $ */ #define BLKSIZE(a, b, c) blksize(a, b, c) @@ -74,6 +74,7 @@ READ(ap) int error; u_short mode; int seqcount; + vm_object_t object; vp = ap->a_vp; seqcount = ap->a_ioflag >> 16; @@ -95,32 +96,56 @@ READ(ap) if ((u_int64_t)uio->uio_offset > fs->fs_maxfilesize) return (EFBIG); - for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { + object = vp->v_object; + + bytesinfile = ip->i_size - uio->uio_offset; + if (bytesinfile <= 0) { + return 0; + } + + if (object) + vm_object_reference(object); +#if 1 + if ((vfs_ioopt > 1) && object) { + int nread, toread; + toread = uio->uio_resid; + if (toread > bytesinfile) + toread = bytesinfile; + if (toread >= PAGE_SIZE) { + error = uioread(toread, uio, object, &nread); + if ((uio->uio_resid == 0) || (error != 0)) { + if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) + ip->i_flag |= IN_ACCESS; + if (object) + vm_object_vndeallocate(object); + return error; + } + } + } +#endif + for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0) break; - -#if 0 - if ((vfs_ioopt > 1) && vp->v_object) { +#if 1 + if ((vfs_ioopt > 1) && object) { int nread, toread; - vm_object_reference(vp->v_object); toread = uio->uio_resid; if (toread > bytesinfile) toread = bytesinfile; if (toread >= PAGE_SIZE) { - error = uioread(toread, uio, vp->v_object, &nread); + error = uioread(toread, uio, object, &nread); if ((uio->uio_resid == 0) || (error != 0)) { if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) ip->i_flag |= IN_ACCESS; - vm_object_vndeallocate(vp->v_object); + if (object) + vm_object_vndeallocate(object); return error; } if (nread > 0) { - vm_object_vndeallocate(vp->v_object); continue; } } - vm_object_vndeallocate(vp->v_object); } #endif @@ -167,13 +192,13 @@ READ(ap) xfersize = size; } - if (vfs_ioopt && + if (vfs_ioopt && object && (bp->b_flags & B_VMIO) && ((blkoffset & PAGE_MASK) == 0) && ((xfersize & PAGE_MASK) == 0)) { error = uiomoveco((char *)bp->b_data + blkoffset, - (int)xfersize, uio, vp->v_object); + (int)xfersize, uio, object); } else { error = uiomove((char *)bp->b_data + blkoffset, @@ -187,6 +212,8 @@ READ(ap) } if (bp != NULL) bqrelse(bp); + if (object) + vm_object_vndeallocate(object); if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) ip->i_flag |= IN_ACCESS; return (error); @@ -214,6 +241,7 @@ WRITE(ap) off_t osize; int blkoffset, error, extended, flags, ioflag, resid, size, xfersize; struct timeval tv; + vm_object_t object; extended = 0; ioflag = ap->a_ioflag; @@ -221,6 +249,10 @@ WRITE(ap) vp = ap->a_vp; ip = VTOI(vp); + object = vp->v_object; + if (object) + vm_object_reference(object); + #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_WRITE) panic("%s: mode", WRITE_S); @@ -230,8 +262,11 @@ WRITE(ap) case VREG: if (ioflag & IO_APPEND) uio->uio_offset = ip->i_size; - if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size) + if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size) { + if (object) + vm_object_vndeallocate(object); return (EPERM); + } /* FALLTHROUGH */ case VLNK: break; @@ -245,8 +280,11 @@ WRITE(ap) fs = ip->I_FS; if (uio->uio_offset < 0 || - (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) + (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) { + if (object) + vm_object_vndeallocate(object); return (EFBIG); + } /* * Maybe this should be above the vnode op call, but so long as * file servers have no limits, I don't think it matters. @@ -256,6 +294,8 @@ WRITE(ap) uio->uio_offset + uio->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { psignal(p, SIGXFSZ); + if (object) + vm_object_vndeallocate(object); return (EFBIG); } @@ -263,6 +303,12 @@ WRITE(ap) osize = ip->i_size; flags = ioflag & IO_SYNC ? B_SYNC : 0; + if (object && (object->flags & OBJ_OPT)) { + vm_freeze_copyopts(object, + OFF_TO_IDX(uio->uio_offset), + OFF_TO_IDX(uio->uio_offset + uio->uio_resid + PAGE_MASK)); + } + for (error = 0; uio->uio_resid > 0;) { lbn = lblkno(fs, uio->uio_offset); blkoffset = blkoff(fs, uio->uio_offset); @@ -292,14 +338,6 @@ WRITE(ap) if (size < xfersize) xfersize = size; - if (vfs_ioopt && - vp->v_object && (vp->v_object->flags & OBJ_OPT) && - vp->v_object->shadow_count) { - vm_freeze_copyopts(vp->v_object, - OFF_TO_IDX(uio->uio_offset), - OFF_TO_IDX(uio->uio_offset + size)); - } - error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); if (ioflag & IO_VMIO) @@ -343,6 +381,9 @@ WRITE(ap) if (!error) VN_POLLEVENT(vp, POLLWRITE | (extended ? POLLEXTEND : 0)); + if (object) + vm_object_vndeallocate(object); + return (error); } diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 9abb81b..801673c 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -59,7 +59,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_glue.c,v 1.70 1998/01/22 17:30:34 dyson Exp $ + * $Id: vm_glue.c,v 1.71 1998/02/04 22:33:44 eivind Exp $ */ #include "opt_diagnostic.h" @@ -214,6 +214,7 @@ vm_fork(p1, p2, flags) } while ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min) { + vm_pageout_deficit += (UPAGES + VM_INITIAL_PAGEIN); VM_WAIT; } @@ -332,13 +333,12 @@ loop: for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { if (p->p_stat == SRUN && (p->p_flag & (P_INMEM | P_SWAPPING)) == 0) { - int mempri; pri = p->p_swtime + p->p_slptime; if ((p->p_flag & P_SWAPINREQ) == 0) { pri -= p->p_nice * 8; } - mempri = pri > 0 ? pri : 0; + /* * if this process is higher priority and there is * enough space, then select this process instead of diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 120a245..794d560 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_kern.c,v 1.41 1998/01/31 11:56:35 dyson Exp $ + * $Id: vm_kern.c,v 1.42 1998/02/04 22:33:45 eivind Exp $ */ /* @@ -180,10 +180,8 @@ kmem_alloc(map, size) for (i = 0; i < size; i += PAGE_SIZE) { vm_page_t mem; - while ((mem = vm_page_alloc(kernel_object, - OFF_TO_IDX(offset + i), VM_ALLOC_ZERO)) == NULL) { - VM_WAIT; - } + mem = vm_page_grab(kernel_object, OFF_TO_IDX(offset + i), + VM_ALLOC_ZERO | VM_ALLOC_RETRY); if ((mem->flags & PG_ZERO) == 0) vm_page_zero_fill(mem); mem->flags &= ~(PG_BUSY|PG_ZERO); @@ -365,7 +363,7 @@ retry: PAGE_WAKEUP(m); pmap_enter(kernel_pmap, addr + i, VM_PAGE_TO_PHYS(m), VM_PROT_ALL, 1); - m->flags |= PG_MAPPED|PG_WRITEABLE; + m->flags |= PG_MAPPED | PG_WRITEABLE | PG_REFERENCED; } vm_map_unlock(map); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 6109761..574693d 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.c,v 1.109 1998/01/31 11:56:38 dyson Exp $ + * $Id: vm_map.c,v 1.110 1998/02/04 22:33:47 eivind Exp $ */ /* @@ -175,7 +175,6 @@ static void vm_map_entry_dispose __P((vm_map_t, vm_map_entry_t)); static void vm_map_entry_unwire __P((vm_map_t, vm_map_entry_t)); static void vm_map_copy_entry __P((vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t)); -static vm_page_t vm_freeze_page_alloc __P((vm_object_t, vm_pindex_t)); void vm_map_startup() @@ -2608,27 +2607,6 @@ vm_uiomove(mapa, srcobject, cp, cnta, uaddra, npages) } /* - * local routine to allocate a page for an object. - */ -static vm_page_t -vm_freeze_page_alloc(object, pindex) - vm_object_t object; - vm_pindex_t pindex; -{ - vm_page_t m; - - while ((m = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL)) == NULL) { - VM_WAIT; - if (m = vm_page_lookup(object, pindex)) - return NULL; - } - - m->valid = 0; - m->dirty = 0; - return m; -} - -/* * Performs the copy_on_write operations necessary to allow the virtual copies * into user space to work. This has to be called for write(2) system calls * from other processes, file unlinking, and file size shrinkage. @@ -2638,7 +2616,7 @@ vm_freeze_copyopts(object, froma, toa) vm_object_t object; vm_pindex_t froma, toa; { - int s; + int s, rv; vm_object_t robject, robjectn; vm_pindex_t idx, from, to; @@ -2674,64 +2652,32 @@ vm_freeze_copyopts(object, froma, toa) for (idx = 0; idx < robject->size; idx++) { m_outretry: - m_out = vm_page_lookup(robject, idx); - if( m_out && (m_out->flags & PG_BUSY)) { - s = splvm(); - while (m_out && (m_out->flags & PG_BUSY)) { - m_out->flags |= PG_WANTED; - tsleep(m_out, PVM, "pwtfrz", 0); - splx(s); - goto m_outretry; - } - splx(s); - } - - if (m_out == NULL) { - m_out = vm_freeze_page_alloc(robject, idx); - if (m_out == NULL) - goto m_outretry; - } + m_out = vm_page_grab(robject, idx, + VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if (m_out->valid == 0) { - m_out->flags |= PG_BUSY; m_inretry: - m_in = vm_page_lookup(object, bo_pindex + idx); - if (m_in == NULL) { - int rv; - m_in = vm_freeze_page_alloc(object, bo_pindex + idx); - if (m_in == NULL) - goto m_inretry; + m_in = vm_page_grab(object, bo_pindex + idx, + VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + if (m_in->valid == 0) { rv = vm_pager_get_pages(object, &m_in, 1, 0); if (rv != VM_PAGER_OK) { printf("vm_freeze_copyopts: cannot read page from file: %x\n", m_in->pindex); continue; } - } else if(m_in->busy || (m_in->flags & PG_BUSY)) { - s = splvm(); - while (m_in && (m_in->busy || (m_in->flags & PG_BUSY))) { - m_in->flags |= PG_WANTED; - tsleep(m_in, PVM, "pwtfrz", 0); - splx(s); - goto m_inretry; - } - splx(s); - if (m_in == NULL) { - goto m_inretry; - } + vm_page_deactivate(m_in); } - m_in->flags |= PG_BUSY; vm_page_protect(m_in, VM_PROT_NONE); pmap_copy_page(VM_PAGE_TO_PHYS(m_in), VM_PAGE_TO_PHYS(m_out)); - m_out->valid = VM_PAGE_BITS_ALL; + m_out->valid = m_in->valid; m_out->dirty = VM_PAGE_BITS_ALL; - vm_page_deactivate(m_out); - vm_page_deactivate(m_in); + vm_page_activate(m_out); - PAGE_WAKEUP(m_out); PAGE_WAKEUP(m_in); } + PAGE_WAKEUP(m_out); } object->shadow_count--; diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index dd3f27c..72c9658 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.c,v 1.109 1998/01/31 11:56:41 dyson Exp $ + * $Id: vm_object.c,v 1.110 1998/02/04 22:33:50 eivind Exp $ */ /* @@ -93,9 +93,7 @@ #include <vm/vm_zone.h> static void vm_object_qcollapse __P((vm_object_t object)); -#ifdef not_used -static void vm_object_deactivate_pages __P((vm_object_t)); -#endif +static void vm_object_dispose __P((vm_object_t)); /* * Virtual memory objects maintain the actual data @@ -249,7 +247,9 @@ vm_object_reference(object) object->ref_count++; if (object->type == OBJT_VNODE) { while (vget((struct vnode *) object->handle, LK_RETRY|LK_NOOBJ, curproc)) { +#if !defined(MAX_PERF) printf("vm_object_reference: delay in getting object\n"); +#endif } } } @@ -381,6 +381,7 @@ doterm: if (temp->ref_count == 0) temp->flags &= ~OBJ_OPT; temp->generation++; + object->backing_object = NULL; } vm_object_terminate(object); /* unlocks and deallocates object */ @@ -418,7 +419,7 @@ vm_object_terminate(object) #if defined(DIAGNOSTIC) if (object->paging_in_progress != 0) - panic("vm_object_deallocate: pageout in progress"); + panic("vm_object_terminate: pageout in progress"); #endif /* @@ -441,28 +442,34 @@ vm_object_terminate(object) vp = (struct vnode *) object->handle; vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); - } else { + } else if (object->type != OBJT_DEAD) { /* * Now free the pages. For internal objects, this also removes them * from paging queues. */ while ((p = TAILQ_FIRST(&object->memq)) != NULL) { +#if !defined(MAX_PERF) if (p->busy || (p->flags & PG_BUSY)) printf("vm_object_terminate: freeing busy page\n"); +#endif p->flags |= PG_BUSY; vm_page_free(p); cnt.v_pfree++; } + } - /* - * Let the pager know object is dead. - */ - vm_pager_deallocate(object); + if (object->type != OBJT_DEAD) { + /* + * Let the pager know object is dead. + */ + vm_pager_deallocate(object); + } if (object->ref_count == 0) { - vm_object_dispose(object); + if ((object->type != OBJT_DEAD) || (object->resident_page_count == 0)) + vm_object_dispose(object); } } @@ -471,7 +478,7 @@ vm_object_terminate(object) * * Dispose the object. */ -void +static void vm_object_dispose(object) vm_object_t object; { diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index e67460e..fe41881 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.h,v 1.43 1998/01/22 17:30:40 dyson Exp $ + * $Id: vm_object.h,v 1.44 1998/01/31 11:56:43 dyson Exp $ */ /* @@ -171,7 +171,6 @@ void vm_object_collapse __P((vm_object_t)); void vm_object_copy __P((vm_object_t, vm_pindex_t, vm_object_t *, vm_pindex_t *, boolean_t *)); void vm_object_deallocate __P((vm_object_t)); void vm_object_terminate __P((vm_object_t)); -void vm_object_dispose __P((vm_object_t)); void vm_object_vndeallocate __P((vm_object_t)); void vm_object_init __P((void)); void vm_object_page_clean __P((vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t)); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 23be218..e0cdd27 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $Id: vm_page.c,v 1.89 1998/01/31 20:30:18 dyson Exp $ + * $Id: vm_page.c,v 1.90 1998/02/04 22:33:52 eivind Exp $ */ /* @@ -96,10 +96,10 @@ static vm_page_t vm_page_select_free __P((vm_object_t object, * page structure. */ -static int vm_page_bucket_generation; /* generation id for buckets */ static struct pglist *vm_page_buckets; /* Array of buckets */ static int vm_page_bucket_count; /* How big is array? */ static int vm_page_hash_mask; /* Mask for hash function */ +static volatile int vm_page_bucket_generation; struct pglist vm_page_queue_free[PQ_L2_SIZE] = {0}; struct pglist vm_page_queue_zero[PQ_L2_SIZE] = {0}; @@ -355,7 +355,6 @@ vm_page_startup(starta, enda, vaddr) pa += PAGE_SIZE; } } - return (mapped); } @@ -391,8 +390,10 @@ vm_page_insert(m, object, pindex) { register struct pglist *bucket; +#if !defined(MAX_PERF) if (m->flags & PG_TABLED) panic("vm_page_insert: already inserted"); +#endif /* * Record the object/offset pair in this page @@ -446,13 +447,16 @@ vm_page_remove(m) register vm_page_t m; { register struct pglist *bucket; + vm_object_t object; if (!(m->flags & PG_TABLED)) return; +#if !defined(MAX_PERF) if ((m->flags & PG_BUSY) == 0) { panic("vm_page_remove: page not busy"); } +#endif m->flags &= ~PG_BUSY; if (m->flags & PG_WANTED) { @@ -460,14 +464,15 @@ vm_page_remove(m) wakeup(m); } - if (m->object->page_hint == m) - m->object->page_hint = NULL; + object = m->object; + if (object->page_hint == m) + object->page_hint = NULL; if (m->wire_count) - m->object->wire_count--; + object->wire_count--; if ((m->queue - m->pc) == PQ_CACHE) - m->object->cache_count--; + object->cache_count--; /* * Remove from the object_object/offset hash table @@ -481,14 +486,15 @@ vm_page_remove(m) * Now remove from the object's list of backed pages. */ - TAILQ_REMOVE(&m->object->memq, m, listq); + TAILQ_REMOVE(&object->memq, m, listq); /* * And show that the object has one fewer resident page. */ - m->object->resident_page_count--; - m->object->generation++; + object->resident_page_count--; + object->generation++; + m->object = NULL; m->flags &= ~PG_TABLED; } @@ -509,25 +515,30 @@ vm_page_lookup(object, pindex) { register vm_page_t m; register struct pglist *bucket; - int curgeneration; + int generation; int s; /* * Search the hash table for this object/offset pair */ - bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; + if (object->page_hint && (object->page_hint->pindex == pindex) && + (object->page_hint->object == object)) + return object->page_hint; -restart: - curgeneration = vm_page_bucket_generation; +retry: + generation = vm_page_bucket_generation; + bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; for (m = TAILQ_FIRST(bucket); m != NULL; m = TAILQ_NEXT(m,hashq)) { - if (curgeneration != vm_page_bucket_generation) - goto restart; if ((m->object == object) && (m->pindex == pindex)) { + if (vm_page_bucket_generation != generation) + goto retry; m->object->page_hint = m; return (m); } } + if (vm_page_bucket_generation != generation) + goto retry; return (NULL); } @@ -569,7 +580,8 @@ vm_page_unqueue_nowakeup(m) (*pq->cnt)--; (*pq->lcnt)--; if ((queue - m->pc) == PQ_CACHE) { - m->object->cache_count--; + if (m->object) + m->object->cache_count--; } } } @@ -593,7 +605,8 @@ vm_page_unqueue(m) if ((cnt.v_cache_count + cnt.v_free_count) < (cnt.v_free_reserved + cnt.v_cache_min)) pagedaemon_wakeup(); - m->object->cache_count--; + if (m->object) + m->object->cache_count--; } } } @@ -890,7 +903,10 @@ vm_page_alloc(object, pindex, page_req) break; default: + m = NULL; +#if !defined(MAX_PERF) panic("vm_page_alloc: invalid allocation class"); +#endif } queue = m->queue; @@ -1045,12 +1061,15 @@ vm_page_freechk_and_unqueue(m) } if (m->wire_count != 0) { +#if !defined(MAX_PERF) if (m->wire_count > 1) { panic("vm_page_free: invalid wire count (%d), pindex: 0x%x", m->wire_count, m->pindex); } +#endif m->wire_count = 0; - m->object->wire_count--; + if (m->object) + m->object->wire_count--; cnt.v_wire_count--; } @@ -1223,7 +1242,9 @@ vm_page_unwire(m) cnt.v_active_count++; } } else { +#if !defined(MAX_PERF) panic("vm_page_unwire: invalid wire count: %d\n", m->wire_count); +#endif } splx(s); } @@ -1278,17 +1299,21 @@ vm_page_cache(m) { int s; +#if !defined(MAX_PERF) if ((m->flags & PG_BUSY) || m->busy || m->wire_count) { printf("vm_page_cache: attempting to cache busy page\n"); return; } +#endif if ((m->queue - m->pc) == PQ_CACHE) return; vm_page_protect(m, VM_PROT_NONE); +#if !defined(MAX_PERF) if (m->dirty != 0) { panic("vm_page_cache: caching a dirty page, pindex: %d", m->pindex); } +#endif s = splvm(); vm_page_unqueue_nowakeup(m); m->queue = PQ_CACHE + m->pc; @@ -1300,6 +1325,54 @@ vm_page_cache(m) splx(s); } +/* + * Grab a page, waiting until we are waken up due to the page + * changing state. We keep on waiting, if the page continues + * to be in the object. If the page doesn't exist, allocate it. + */ +vm_page_t +vm_page_grab(object, pindex, allocflags) + vm_object_t object; + vm_pindex_t pindex; + int allocflags; +{ + + vm_page_t m; + int s, generation; + +retrylookup: + if ((m = vm_page_lookup(object, pindex)) != NULL) { + if (m->busy || (m->flags & PG_BUSY)) { + generation = object->generation; + + s = splvm(); + while ((object->generation == generation) && + (m->busy || (m->flags & PG_BUSY))) { + m->flags |= PG_WANTED | PG_REFERENCED; + tsleep(m, PVM, "pgrbwt", 0); + if ((allocflags & VM_ALLOC_RETRY) == 0) { + splx(s); + return NULL; + } + } + splx(s); + goto retrylookup; + } else { + m->flags |= PG_BUSY; + return m; + } + } + + m = vm_page_alloc(object, pindex, allocflags & ~VM_ALLOC_RETRY); + if (m == NULL) { + VM_WAIT; + if ((allocflags & VM_ALLOC_RETRY) == 0) + return NULL; + goto retrylookup; + } + + return m; +} /* * mapping function for valid bits or for dirty bits in @@ -1400,12 +1473,14 @@ contigmalloc1(size, type, flags, low, high, alignment, boundary, map) vm_page_t pga = vm_page_array; size = round_page(size); +#if !defined(MAX_PERF) if (size == 0) panic("contigmalloc1: size must not be 0"); if ((alignment & (alignment - 1)) != 0) panic("contigmalloc1: alignment must be a power of 2"); if ((boundary & (boundary - 1)) != 0) panic("contigmalloc1: boundary must be a power of 2"); +#endif start = 0; for (pass = 0; pass <= 1; pass++) { diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 1042463..8a819bb 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id$ + * $Id: vm_page.h,v 1.35 1997/02/22 09:48:32 peter Exp $ */ /* @@ -284,13 +284,15 @@ extern vm_offset_t last_phys_addr; /* physical address for last_page */ #define VM_PAGE_BITS_ALL 0xffff #endif -#define VM_ALLOC_NORMAL 0 -#define VM_ALLOC_INTERRUPT 1 -#define VM_ALLOC_SYSTEM 2 -#define VM_ALLOC_ZERO 3 +#define VM_ALLOC_NORMAL 0 +#define VM_ALLOC_INTERRUPT 1 +#define VM_ALLOC_SYSTEM 2 +#define VM_ALLOC_ZERO 3 +#define VM_ALLOC_RETRY 0x80 void vm_page_activate __P((vm_page_t)); vm_page_t vm_page_alloc __P((vm_object_t, vm_pindex_t, int)); +vm_page_t vm_page_grab __P((vm_object_t, vm_pindex_t, int)); void vm_page_cache __P((register vm_page_t)); static __inline void vm_page_copy __P((vm_page_t, vm_page_t)); void vm_page_deactivate __P((vm_page_t)); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 66e2988..11c4d9f 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -65,7 +65,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.c,v 1.110 1998/01/31 11:56:49 dyson Exp $ + * $Id: vm_pageout.c,v 1.111 1998/02/04 22:33:56 eivind Exp $ */ /* @@ -369,7 +369,7 @@ vm_pageout_flush(mc, count, sync) { register vm_object_t object; int pageout_status[count]; - int anyok = 0; + int numpagedout = 0; int i; object = mc[0]->object; @@ -384,10 +384,10 @@ vm_pageout_flush(mc, count, sync) switch (pageout_status[i]) { case VM_PAGER_OK: - anyok++; + numpagedout++; break; case VM_PAGER_PEND: - anyok++; + numpagedout++; break; case VM_PAGER_BAD: /* @@ -423,7 +423,7 @@ vm_pageout_flush(mc, count, sync) PAGE_WAKEUP(mt); } } - return anyok; + return numpagedout; } #if !defined(NO_SWAPPING) @@ -644,6 +644,7 @@ vm_pageout_scan() pages_freed = 0; addl_page_shortage = vm_pageout_deficit; + vm_pageout_deficit = 0; if (max_page_launder == 0) max_page_launder = 1; diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 8f473c1..352c4a0 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 - * $Id: vnode_pager.c,v 1.81 1998/01/31 11:56:53 dyson Exp $ + * $Id: vnode_pager.c,v 1.82 1998/02/04 22:34:03 eivind Exp $ */ /* @@ -181,9 +181,9 @@ vnode_pager_dealloc(object) } object->handle = NULL; - object->type = OBJT_DEFAULT; + object->type = OBJT_DEAD; vp->v_object = NULL; - vp->v_flag &= ~(VTEXT|VOBJBUF); + vp->v_flag &= ~(VTEXT | VOBJBUF); } static boolean_t @@ -763,7 +763,10 @@ vnode_pager_leaf_getpages(object, m, count, reqpage) * now tell them that it is ok to use */ if (!error) { - vm_page_deactivate(m[i]); + if (m[i]->flags & PG_WANTED) + vm_page_activate(m[i]); + else + vm_page_deactivate(m[i]); PAGE_WAKEUP(m[i]); } else { vnode_pager_freepage(m[i]); @@ -880,8 +883,10 @@ vnode_pager_leaf_putpages(object, m, count, sync, rtvals) if (i < ncount) { rtvals[i] = VM_PAGER_OK; } - if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED)) + if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED)) { + vm_page_activate(m[i]); wakeup(m[i]); + } } return rtvals[0]; } |