|
|
| version 1.38, 2004/05/05 22:09:16 | version 1.39, 2004/05/13 17:40:14 |
|---|---|
| Line 863 pmap_qremove(vm_offset_t va, int count) | Line 863 pmap_qremove(vm_offset_t va, int count) |
| #endif | #endif |
| } | } |
| /* | |
| * This routine works like vm_page_lookup() but also blocks as long as the | |
| * page is busy. This routine does not busy the page it returns. | |
| * | |
| * Unless the caller is managing objects whos pages are in a known state, | |
| * the call should be made at splvm() so the page's object association | |
| * remains valid on return. | |
| */ | |
| static vm_page_t | static vm_page_t |
| pmap_page_lookup(vm_object_t object, vm_pindex_t pindex) | pmap_page_lookup(vm_object_t object, vm_pindex_t pindex) |
| { | { |
| vm_page_t m; | vm_page_t m; |
| retry: | retry: |
| m = vm_page_lookup(object, pindex); | m = vm_page_lookup(object, pindex); |
| if (m && vm_page_sleep_busy(m, FALSE, "pplookp")) | if (m && vm_page_sleep_busy(m, FALSE, "pplookp")) |
| goto retry; | goto retry; |
| return m; | return(m); |
| } | } |
| /* | /* |
| Line 930 pmap_swapout_proc(struct proc *p) | Line 939 pmap_swapout_proc(struct proc *p) |
| { | { |
| #if 0 | #if 0 |
| int i; | int i; |
| int s; | |
| vm_object_t upobj; | vm_object_t upobj; |
| vm_page_t m; | vm_page_t m; |
| upobj = p->p_upages_obj; | upobj = p->p_upages_obj; |
| /* | /* |
| * let the upages be paged | * Unwiring the pages allow them to be paged to their backing store |
| * (swap). | |
| * | |
| * splvm() protection not required since nobody will be messing with | |
| * the pages but us. | |
| */ | */ |
| for(i=0;i<UPAGES;i++) { | for (i = 0; i < UPAGES; i++) { |
| if ((m = vm_page_lookup(upobj, i)) == NULL) | if ((m = vm_page_lookup(upobj, i)) == NULL) |
| panic("pmap_swapout_proc: upage already missing???"); | panic("pmap_swapout_proc: upage already missing???"); |
| vm_page_dirty(m); | vm_page_dirty(m); |
| Line 958 pmap_swapin_proc(struct proc *p) | Line 973 pmap_swapin_proc(struct proc *p) |
| vm_object_t upobj; | vm_object_t upobj; |
| vm_page_t m; | vm_page_t m; |
| /* | |
| * splvm() protection not required since nobody will be messing with | |
| * the pages but us. | |
| */ | |
| upobj = p->p_upages_obj; | upobj = p->p_upages_obj; |
| for(i=0;i<UPAGES;i++) { | for (i = 0; i < UPAGES; i++) { |
| m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); | m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); |
| pmap_kenter((vm_offset_t)p->p_addr + (i * PAGE_SIZE), | pmap_kenter((vm_offset_t)p->p_addr + (i * PAGE_SIZE), |
| Line 973 pmap_swapin_proc(struct proc *p) | Line 991 pmap_swapin_proc(struct proc *p) |
| m = vm_page_lookup(upobj, i); | m = vm_page_lookup(upobj, i); |
| m->valid = VM_PAGE_BITS_ALL; | m->valid = VM_PAGE_BITS_ALL; |
| } | } |
| vm_page_wire(m); | vm_page_wire(m); |
| vm_page_wakeup(m); | vm_page_wakeup(m); |
| vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE); | vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE); |
| Line 1327 pmap_release(struct pmap *pmap) | Line 1344 pmap_release(struct pmap *pmap) |
| vm_page_t p,n,ptdpg; | vm_page_t p,n,ptdpg; |
| vm_object_t object = pmap->pm_pteobj; | vm_object_t object = pmap->pm_pteobj; |
| int curgeneration; | int curgeneration; |
| int s; | |
| #if defined(DIAGNOSTIC) | #if defined(DIAGNOSTIC) |
| if (object->ref_count != 1) | if (object->ref_count != 1) |
| Line 1335 pmap_release(struct pmap *pmap) | Line 1353 pmap_release(struct pmap *pmap) |
| ptdpg = NULL; | ptdpg = NULL; |
| retry: | retry: |
| s = splvm(); | |
| curgeneration = object->generation; | curgeneration = object->generation; |
| for (p = TAILQ_FIRST(&object->memq); p != NULL; p = n) { | for (p = TAILQ_FIRST(&object->memq); p != NULL; p = n) { |
| n = TAILQ_NEXT(p, listq); | n = TAILQ_NEXT(p, listq); |
| Line 1344 retry: | Line 1363 retry: |
| } | } |
| while (1) { | while (1) { |
| if (!pmap_release_free_page(pmap, p) && | if (!pmap_release_free_page(pmap, p) && |
| (object->generation != curgeneration)) | (object->generation != curgeneration)) { |
| splx(s); | |
| goto retry; | goto retry; |
| } | |
| } | } |
| } | } |
| splx(s); | |
| if (ptdpg && !pmap_release_free_page(pmap, ptdpg)) | if (ptdpg && !pmap_release_free_page(pmap, ptdpg)) |
| goto retry; | goto retry; |
| Line 2197 pmap_kenter_temporary(vm_paddr_t pa, int | Line 2219 pmap_kenter_temporary(vm_paddr_t pa, int |
| } | } |
| #define MAX_INIT_PT (96) | #define MAX_INIT_PT (96) |
| /* | /* |
| * pmap_object_init_pt preloads the ptes for a given object | * This routine preloads the ptes for a given object into the specified pmap. |
| * into the specified pmap. This eliminates the blast of soft | * This eliminates the blast of soft faults on process startup and |
| * faults on process startup and immediately after an mmap. | * immediately after an mmap. |
| */ | */ |
| void | void |
| pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_prot_t prot, | pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_prot_t prot, |
| Line 2211 pmap_object_init_pt(pmap_t pmap, vm_offs | Line 2234 pmap_object_init_pt(pmap_t pmap, vm_offs |
| int psize; | int psize; |
| vm_page_t p, mpte; | vm_page_t p, mpte; |
| int objpgs; | int objpgs; |
| int s; | |
| if ((prot & VM_PROT_READ) == 0 || pmap == NULL || object == NULL) | if ((prot & VM_PROT_READ) == 0 || pmap == NULL || object == NULL) |
| return; | return; |
| #if 0 | |
| /* | |
| * XXX you must be joking, entering PTE's into a user page table | |
| * without any accounting? This could result in the page table | |
| * being freed while it still contains mappings (free with PG_ZERO | |
| * assumption leading to a non-zero page being marked PG_ZERO). | |
| */ | |
| /* | /* |
| * This code maps large physical mmap regions into the | * This code maps large physical mmap regions into the |
| * processor address space. Note that some shortcuts | * processor address space. Note that some shortcuts |
| * are taken, but the code works. | * are taken, but the code works. |
| */ | */ |
| if (pseflag && | if (pseflag && |
| (object->type == OBJT_DEVICE) && | (object->type == OBJT_DEVICE) && |
| ((addr & (NBPDR - 1)) == 0) && | ((addr & (NBPDR - 1)) == 0) && |
| ((size & (NBPDR - 1)) == 0) ) { | ((size & (NBPDR - 1)) == 0) ) { |
| int i; | int i; |
| vm_page_t m[1]; | vm_page_t m[1]; |
| unsigned int ptepindex; | unsigned int ptepindex; |
| Line 2262 retry: | Line 2293 retry: |
| pmap->pm_stats.resident_count += size >> PAGE_SHIFT; | pmap->pm_stats.resident_count += size >> PAGE_SHIFT; |
| npdes = size >> PDRSHIFT; | npdes = size >> PDRSHIFT; |
| for(i=0;i<npdes;i++) { | for (i = 0; i < npdes; i++) { |
| pmap->pm_pdir[ptepindex] = | pmap->pm_pdir[ptepindex] = |
| (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V | PG_PS); | (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V | PG_PS); |
| ptepa += NBPDR; | ptepa += NBPDR; |
| ptepindex += 1; | ptepindex += 1; |
| } | } |
| Line 2273 retry: | Line 2304 retry: |
| smp_invltlb(); | smp_invltlb(); |
| return; | return; |
| } | } |
| #endif | |
| psize = i386_btop(size); | psize = i386_btop(size); |
| Line 2288 retry: | Line 2320 retry: |
| psize = object->size - pindex; | psize = object->size - pindex; |
| } | } |
| mpte = NULL; | |
| /* | /* |
| * if we are processing a major portion of the object, then scan the | * If we are processing a major portion of the object, then scan the |
| * entire thing. | * entire thing. |
| * | |
| * We cannot safely scan the object's memq unless we are at splvm(), | |
| * since interrupts can remove pages from objects. | |
| */ | */ |
| s = splvm(); | |
| mpte = NULL; | |
| if (psize > (object->resident_page_count >> 2)) { | if (psize > (object->resident_page_count >> 2)) { |
| objpgs = psize; | objpgs = psize; |
| for (p = TAILQ_FIRST(&object->memq); | for (p = TAILQ_FIRST(&object->memq); |
| ((objpgs > 0) && (p != NULL)); | objpgs > 0 && p != NULL; |
| p = TAILQ_NEXT(p, listq)) { | p = TAILQ_NEXT(p, listq) |
| ) { | |
| tmpidx = p->pindex; | tmpidx = p->pindex; |
| if (tmpidx < pindex) { | if (tmpidx < pindex) |
| continue; | continue; |
| } | |
| tmpidx -= pindex; | tmpidx -= pindex; |
| if (tmpidx >= psize) { | if (tmpidx >= psize) |
| continue; | continue; |
| } | |
| /* | /* |
| * don't allow an madvise to blow away our really | * don't allow an madvise to blow away our really |
| * free pages allocating pv entries. | * free pages allocating pv entries. |
| Line 2357 retry: | Line 2393 retry: |
| } | } |
| } | } |
| } | } |
| splx(s); | |
| } | } |
| /* | /* |
| * pmap_prefault provides a quick way of clustering | * pmap_prefault provides a quick way of clustering pagefaults into a |
| * pagefaults into a processes address space. It is a "cousin" | * processes address space. It is a "cousin" of pmap_object_init_pt, |
| * of pmap_object_init_pt, except it runs at page fault time instead | * except it runs at page fault time instead of mmap time. |
| * of mmap time. | |
| */ | */ |
| #define PFBAK 4 | #define PFBAK 4 |
| #define PFFOR 4 | #define PFFOR 4 |
| Line 2380 void | Line 2416 void |
| pmap_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry) | pmap_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry) |
| { | { |
| int i; | int i; |
| int s; | |
| vm_offset_t starta; | vm_offset_t starta; |
| vm_offset_t addr; | vm_offset_t addr; |
| vm_pindex_t pindex; | vm_pindex_t pindex; |
| Line 2392 pmap_prefault(pmap_t pmap, vm_offset_t a | Line 2429 pmap_prefault(pmap_t pmap, vm_offset_t a |
| object = entry->object.vm_object; | object = entry->object.vm_object; |
| starta = addra - PFBAK * PAGE_SIZE; | starta = addra - PFBAK * PAGE_SIZE; |
| if (starta < entry->start) { | if (starta < entry->start) |
| starta = entry->start; | starta = entry->start; |
| } else if (starta > addra) { | else if (starta > addra) |
| starta = 0; | starta = 0; |
| } | |
| /* | |
| * splvm() protection is required to maintain the page/object | |
| * association, interrupts can free pages and remove them from | |
| * their objects. | |
| */ | |
| mpte = NULL; | mpte = NULL; |
| s = splvm(); | |
| for (i = 0; i < PAGEORDER_SIZE; i++) { | for (i = 0; i < PAGEORDER_SIZE; i++) { |
| vm_object_t lobject; | vm_object_t lobject; |
| unsigned *pte; | unsigned *pte; |
| Line 2419 pmap_prefault(pmap_t pmap, vm_offset_t a | Line 2461 pmap_prefault(pmap_t pmap, vm_offset_t a |
| pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT; | pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT; |
| lobject = object; | lobject = object; |
| for (m = vm_page_lookup(lobject, pindex); | for (m = vm_page_lookup(lobject, pindex); |
| (!m && (lobject->type == OBJT_DEFAULT) && (lobject->backing_object)); | (!m && (lobject->type == OBJT_DEFAULT) && |
| lobject = lobject->backing_object) { | (lobject->backing_object)); |
| lobject = lobject->backing_object | |
| ) { | |
| if (lobject->backing_object_offset & PAGE_MASK) | if (lobject->backing_object_offset & PAGE_MASK) |
| break; | break; |
| pindex += (lobject->backing_object_offset >> PAGE_SHIFT); | pindex += (lobject->backing_object_offset >> PAGE_SHIFT); |
| Line 2447 pmap_prefault(pmap_t pmap, vm_offset_t a | Line 2492 pmap_prefault(pmap_t pmap, vm_offset_t a |
| vm_page_wakeup(m); | vm_page_wakeup(m); |
| } | } |
| } | } |
| splx(s); | |
| } | } |
| /* | /* |
| Line 2510 pmap_copy(pmap_t dst_pmap, pmap_t src_pm | Line 2556 pmap_copy(pmap_t dst_pmap, pmap_t src_pm |
| vm_offset_t pdnxt; | vm_offset_t pdnxt; |
| unsigned src_frame, dst_frame; | unsigned src_frame, dst_frame; |
| vm_page_t m; | vm_page_t m; |
| int s; | |
| if (dst_addr != src_addr) | if (dst_addr != src_addr) |
| return; | return; |
| Line 2529 pmap_copy(pmap_t dst_pmap, pmap_t src_pm | Line 2576 pmap_copy(pmap_t dst_pmap, pmap_t src_pm |
| pmap_inval_add(&info, dst_pmap, -1); | pmap_inval_add(&info, dst_pmap, -1); |
| pmap_inval_add(&info, src_pmap, -1); | pmap_inval_add(&info, src_pmap, -1); |
| for(addr = src_addr; addr < end_addr; addr = pdnxt) { | /* |
| * splvm() protection is required to maintain the page/object | |
| * association, interrupts can free pages and remove them from | |
| * their objects. | |
| */ | |
| s = splvm(); | |
| for (addr = src_addr; addr < end_addr; addr = pdnxt) { | |
| unsigned *src_pte, *dst_pte; | unsigned *src_pte, *dst_pte; |
| vm_page_t dstmpte, srcmpte; | vm_page_t dstmpte, srcmpte; |
| vm_offset_t srcptepaddr; | vm_offset_t srcptepaddr; |
| Line 2607 pmap_copy(pmap_t dst_pmap, pmap_t src_pm | Line 2660 pmap_copy(pmap_t dst_pmap, pmap_t src_pm |
| dst_pte++; | dst_pte++; |
| } | } |
| } | } |
| splx(s); | |
| pmap_inval_flush(&info); | pmap_inval_flush(&info); |
| } | } |