145748Smckusick /* 263379Sbostic * Copyright (c) 1991, 1993 363379Sbostic * The Regents of the University of California. All rights reserved. 445748Smckusick * 547663Smckusick * This code is derived from software contributed to Berkeley by 647663Smckusick * The Mach Operating System project at Carnegie-Mellon University. 747663Smckusick * 847663Smckusick * %sccs.include.redist.c% 947663Smckusick * 10*68164Scgd * @(#)vm_fault.c 8.5 (Berkeley) 01/09/95 1147663Smckusick * 1247663Smckusick * 1347663Smckusick * Copyright (c) 1987, 1990 Carnegie-Mellon University. 1447663Smckusick * All rights reserved. 1547663Smckusick * 1647592Smckusick * Authors: Avadis Tevanian, Jr., Michael Wayne Young 1747592Smckusick * 1847592Smckusick * Permission to use, copy, modify and distribute this software and 1947592Smckusick * its documentation is hereby granted, provided that both the copyright 2047592Smckusick * notice and this permission notice appear in all copies of the 2147592Smckusick * software, derivative works or modified versions, and any portions 2247592Smckusick * thereof, and that both notices appear in supporting documentation. 2347592Smckusick * 2447592Smckusick * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 2547592Smckusick * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 2647592Smckusick * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2747592Smckusick * 2847663Smckusick * Carnegie Mellon requests users of this software to return to 2945748Smckusick * 3047663Smckusick * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 3147663Smckusick * School of Computer Science 3247663Smckusick * Carnegie Mellon University 3347663Smckusick * Pittsburgh PA 15213-3890 3447662Smckusick * 3547663Smckusick * any improvements or extensions that they make and grant Carnegie the 3647663Smckusick * rights to redistribute these changes. 3745748Smckusick */ 3845748Smckusick 3945748Smckusick /* 4045748Smckusick * Page fault handling module. 4145748Smckusick */ 4245748Smckusick 4353348Sbostic #include <sys/param.h> 4453348Sbostic #include <sys/systm.h> 4545748Smckusick 4653348Sbostic #include <vm/vm.h> 4753348Sbostic #include <vm/vm_page.h> 4853348Sbostic #include <vm/vm_pageout.h> 4948386Skarels 5045748Smckusick /* 5145748Smckusick * vm_fault: 5245748Smckusick * 5345748Smckusick * Handle a page fault occuring at the given address, 5445748Smckusick * requiring the given permissions, in the map specified. 5545748Smckusick * If successful, the page is inserted into the 5645748Smckusick * associated physical map. 5745748Smckusick * 5845748Smckusick * NOTE: the given address should be truncated to the 5945748Smckusick * proper page address. 6045748Smckusick * 6145748Smckusick * KERN_SUCCESS is returned if the page fault is handled; otherwise, 6245748Smckusick * a standard error specifying why the fault is fatal is returned. 6345748Smckusick * 6445748Smckusick * 6545748Smckusick * The map in question must be referenced, and remains so. 6645748Smckusick * Caller may hold no locks. 6745748Smckusick */ 6853348Sbostic int 6945748Smckusick vm_fault(map, vaddr, fault_type, change_wiring) 7045748Smckusick vm_map_t map; 7145748Smckusick vm_offset_t vaddr; 7245748Smckusick vm_prot_t fault_type; 7345748Smckusick boolean_t change_wiring; 7445748Smckusick { 7545748Smckusick vm_object_t first_object; 7645748Smckusick vm_offset_t first_offset; 7745748Smckusick vm_map_entry_t entry; 7845748Smckusick register vm_object_t object; 7945748Smckusick register vm_offset_t offset; 8045748Smckusick register vm_page_t m; 8145748Smckusick vm_page_t first_m; 8245748Smckusick vm_prot_t prot; 8345748Smckusick int result; 8445748Smckusick boolean_t wired; 8545748Smckusick boolean_t su; 8645748Smckusick boolean_t lookup_still_valid; 8745748Smckusick boolean_t page_exists; 8845748Smckusick vm_page_t old_m; 8945748Smckusick vm_object_t next_object; 9045748Smckusick 9165684Shibler cnt.v_faults++; /* needs lock XXX */ 9245748Smckusick /* 9345748Smckusick * Recovery actions 9445748Smckusick */ 9545748Smckusick #define FREE_PAGE(m) { \ 9645748Smckusick PAGE_WAKEUP(m); \ 9745748Smckusick vm_page_lock_queues(); \ 9845748Smckusick vm_page_free(m); \ 9945748Smckusick vm_page_unlock_queues(); \ 10045748Smckusick } 10145748Smckusick 10245748Smckusick #define RELEASE_PAGE(m) { \ 10345748Smckusick PAGE_WAKEUP(m); \ 10445748Smckusick vm_page_lock_queues(); \ 10545748Smckusick vm_page_activate(m); \ 10645748Smckusick vm_page_unlock_queues(); \ 10745748Smckusick } 10845748Smckusick 10945748Smckusick #define UNLOCK_MAP { \ 11045748Smckusick if (lookup_still_valid) { \ 11145748Smckusick vm_map_lookup_done(map, entry); \ 11245748Smckusick lookup_still_valid = FALSE; \ 11345748Smckusick } \ 11445748Smckusick } 11545748Smckusick 11645748Smckusick #define UNLOCK_THINGS { \ 11745748Smckusick object->paging_in_progress--; \ 11845748Smckusick vm_object_unlock(object); \ 11945748Smckusick if (object != first_object) { \ 12045748Smckusick vm_object_lock(first_object); \ 12145748Smckusick FREE_PAGE(first_m); \ 12245748Smckusick first_object->paging_in_progress--; \ 12345748Smckusick vm_object_unlock(first_object); \ 12445748Smckusick } \ 12545748Smckusick UNLOCK_MAP; \ 12645748Smckusick } 12745748Smckusick 12845748Smckusick #define UNLOCK_AND_DEALLOCATE { \ 12945748Smckusick UNLOCK_THINGS; \ 13045748Smckusick vm_object_deallocate(first_object); \ 13145748Smckusick } 13245748Smckusick 13345748Smckusick RetryFault: ; 13445748Smckusick 13545748Smckusick /* 13645748Smckusick * Find the backing store object and offset into 13745748Smckusick * it to begin the search. 13845748Smckusick */ 13945748Smckusick 14045748Smckusick if ((result = vm_map_lookup(&map, vaddr, fault_type, &entry, 14145748Smckusick &first_object, &first_offset, 14245748Smckusick &prot, &wired, &su)) != KERN_SUCCESS) { 14345748Smckusick return(result); 14445748Smckusick } 14545748Smckusick lookup_still_valid = TRUE; 14645748Smckusick 14745748Smckusick if (wired) 14845748Smckusick fault_type = prot; 14945748Smckusick 15048386Skarels first_m = NULL; 15145748Smckusick 15245748Smckusick /* 15345748Smckusick * Make a reference to this object to 15445748Smckusick * prevent its disposal while we are messing with 15545748Smckusick * it. Once we have the reference, the map is free 15645748Smckusick * to be diddled. Since objects reference their 15745748Smckusick * shadows (and copies), they will stay around as well. 15845748Smckusick */ 15945748Smckusick 16045748Smckusick vm_object_lock(first_object); 16145748Smckusick 16245748Smckusick first_object->ref_count++; 16345748Smckusick first_object->paging_in_progress++; 16445748Smckusick 16545748Smckusick /* 16645748Smckusick * INVARIANTS (through entire routine): 16745748Smckusick * 16845748Smckusick * 1) At all times, we must either have the object 16945748Smckusick * lock or a busy page in some object to prevent 17045748Smckusick * some other thread from trying to bring in 17145748Smckusick * the same page. 17245748Smckusick * 17345748Smckusick * Note that we cannot hold any locks during the 17445748Smckusick * pager access or when waiting for memory, so 17545748Smckusick * we use a busy page then. 17645748Smckusick * 17745748Smckusick * Note also that we aren't as concerned about 17845748Smckusick * more than one thead attempting to pager_data_unlock 17945748Smckusick * the same page at once, so we don't hold the page 18045748Smckusick * as busy then, but do record the highest unlock 18145748Smckusick * value so far. [Unlock requests may also be delivered 18245748Smckusick * out of order.] 18345748Smckusick * 18445748Smckusick * 2) Once we have a busy page, we must remove it from 18545748Smckusick * the pageout queues, so that the pageout daemon 18645748Smckusick * will not grab it away. 18745748Smckusick * 18845748Smckusick * 3) To prevent another thread from racing us down the 18945748Smckusick * shadow chain and entering a new page in the top 19045748Smckusick * object before we do, we must keep a busy page in 19145748Smckusick * the top object while following the shadow chain. 19245748Smckusick * 19345748Smckusick * 4) We must increment paging_in_progress on any object 19445748Smckusick * for which we have a busy page, to prevent 19545748Smckusick * vm_object_collapse from removing the busy page 19645748Smckusick * without our noticing. 19745748Smckusick */ 19845748Smckusick 19945748Smckusick /* 20045748Smckusick * Search for the page at object/offset. 20145748Smckusick */ 20245748Smckusick 20345748Smckusick object = first_object; 20445748Smckusick offset = first_offset; 20545748Smckusick 20645748Smckusick /* 20745748Smckusick * See whether this page is resident 20845748Smckusick */ 20945748Smckusick 21045748Smckusick while (TRUE) { 21145748Smckusick m = vm_page_lookup(object, offset); 21248386Skarels if (m != NULL) { 21345748Smckusick /* 21445748Smckusick * If the page is being brought in, 21545748Smckusick * wait for it and then retry. 21645748Smckusick */ 21756382Smckusick if (m->flags & PG_BUSY) { 21845748Smckusick #ifdef DOTHREADS 21945748Smckusick int wait_result; 22045748Smckusick 22145748Smckusick PAGE_ASSERT_WAIT(m, !change_wiring); 22245748Smckusick UNLOCK_THINGS; 22345748Smckusick thread_block(); 22445748Smckusick wait_result = current_thread()->wait_result; 22545748Smckusick vm_object_deallocate(first_object); 22645748Smckusick if (wait_result != THREAD_AWAKENED) 22745748Smckusick return(KERN_SUCCESS); 22845748Smckusick goto RetryFault; 22945748Smckusick #else 23045748Smckusick PAGE_ASSERT_WAIT(m, !change_wiring); 23145748Smckusick UNLOCK_THINGS; 23265684Shibler cnt.v_intrans++; 23345748Smckusick thread_block(); 23445748Smckusick vm_object_deallocate(first_object); 23545748Smckusick goto RetryFault; 23645748Smckusick #endif 23745748Smckusick } 23845748Smckusick 23945748Smckusick /* 24045748Smckusick * Remove the page from the pageout daemon's 24145748Smckusick * reach while we play with it. 24245748Smckusick */ 24345748Smckusick 24445748Smckusick vm_page_lock_queues(); 24556382Smckusick if (m->flags & PG_INACTIVE) { 24665231Smckusick TAILQ_REMOVE(&vm_page_queue_inactive, m, pageq); 24756382Smckusick m->flags &= ~PG_INACTIVE; 24850911Smckusick cnt.v_inactive_count--; 24950911Smckusick cnt.v_reactivated++; 25045748Smckusick } 25145748Smckusick 25256382Smckusick if (m->flags & PG_ACTIVE) { 25365231Smckusick TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 25456382Smckusick m->flags &= ~PG_ACTIVE; 25550911Smckusick cnt.v_active_count--; 25645748Smckusick } 25745748Smckusick vm_page_unlock_queues(); 25845748Smckusick 25945748Smckusick /* 26045748Smckusick * Mark page busy for other threads. 26145748Smckusick */ 26256382Smckusick m->flags |= PG_BUSY; 26345748Smckusick break; 26445748Smckusick } 26545748Smckusick 26648386Skarels if (((object->pager != NULL) && 26745748Smckusick (!change_wiring || wired)) 26845748Smckusick || (object == first_object)) { 26945748Smckusick 27045748Smckusick /* 27145748Smckusick * Allocate a new page for this object/offset 27245748Smckusick * pair. 27345748Smckusick */ 27445748Smckusick 27545748Smckusick m = vm_page_alloc(object, offset); 27645748Smckusick 27748386Skarels if (m == NULL) { 27845748Smckusick UNLOCK_AND_DEALLOCATE; 27945748Smckusick VM_WAIT; 28045748Smckusick goto RetryFault; 28145748Smckusick } 28245748Smckusick } 28345748Smckusick 28456323Shibler if (object->pager != NULL && (!change_wiring || wired)) { 28545748Smckusick int rv; 28645748Smckusick 28745748Smckusick /* 28845748Smckusick * Now that we have a busy page, we can 28945748Smckusick * release the object lock. 29045748Smckusick */ 29145748Smckusick vm_object_unlock(object); 29245748Smckusick 29345748Smckusick /* 29445748Smckusick * Call the pager to retrieve the data, if any, 29545748Smckusick * after releasing the lock on the map. 29645748Smckusick */ 29745748Smckusick UNLOCK_MAP; 29865684Shibler cnt.v_pageins++; 29956323Shibler rv = vm_pager_get(object->pager, m, TRUE); 30045748Smckusick 30156323Shibler /* 30256323Shibler * Reaquire the object lock to preserve our 30356323Shibler * invariant. 30456323Shibler */ 30556323Shibler vm_object_lock(object); 30656323Shibler 30756323Shibler /* 30856323Shibler * Found the page. 30956323Shibler * Leave it busy while we play with it. 31056323Shibler */ 31145748Smckusick if (rv == VM_PAGER_OK) { 31245748Smckusick /* 31345748Smckusick * Relookup in case pager changed page. 31445748Smckusick * Pager is responsible for disposition 31545748Smckusick * of old page if moved. 31645748Smckusick */ 31745748Smckusick m = vm_page_lookup(object, offset); 31845748Smckusick 31965684Shibler cnt.v_pgpgin++; 32056382Smckusick m->flags &= ~PG_FAKE; 32156382Smckusick m->flags |= PG_CLEAN; 32245748Smckusick pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 32345748Smckusick break; 32445748Smckusick } 32545748Smckusick 32645748Smckusick /* 32756323Shibler * IO error or page outside the range of the pager: 32856323Shibler * cleanup and return an error. 32945748Smckusick */ 33056323Shibler if (rv == VM_PAGER_ERROR || rv == VM_PAGER_BAD) { 33145748Smckusick FREE_PAGE(m); 33245748Smckusick UNLOCK_AND_DEALLOCATE; 33345748Smckusick return(KERN_PROTECTION_FAILURE); /* XXX */ 33445748Smckusick } 33556323Shibler /* 33656323Shibler * rv == VM_PAGER_FAIL: 33756323Shibler * 33856323Shibler * Page does not exist at this object/offset. 33956323Shibler * Free the bogus page (waking up anyone waiting 34056323Shibler * for it) and continue on to the next object. 34156323Shibler * 34256323Shibler * If this is the top-level object, we must 34356323Shibler * leave the busy page to prevent another 34456323Shibler * thread from rushing past us, and inserting 34556323Shibler * the page in that object at the same time 34656323Shibler * that we are. 34756323Shibler */ 34845748Smckusick if (object != first_object) { 34945748Smckusick FREE_PAGE(m); 35053941Shibler /* note that `m' is not used after this */ 35145748Smckusick } 35245748Smckusick } 35345748Smckusick 35445748Smckusick /* 35545748Smckusick * We get here if the object has no pager (or unwiring) 35645748Smckusick * or the pager doesn't have the page. 35745748Smckusick */ 35845748Smckusick if (object == first_object) 35945748Smckusick first_m = m; 36045748Smckusick 36145748Smckusick /* 36245748Smckusick * Move on to the next object. Lock the next 36345748Smckusick * object before unlocking the current one. 36445748Smckusick */ 36545748Smckusick 36645748Smckusick offset += object->shadow_offset; 36745748Smckusick next_object = object->shadow; 36848386Skarels if (next_object == NULL) { 36945748Smckusick /* 37045748Smckusick * If there's no object left, fill the page 37145748Smckusick * in the top object with zeros. 37245748Smckusick */ 37345748Smckusick if (object != first_object) { 37445748Smckusick object->paging_in_progress--; 37545748Smckusick vm_object_unlock(object); 37645748Smckusick 37745748Smckusick object = first_object; 37845748Smckusick offset = first_offset; 37945748Smckusick m = first_m; 38045748Smckusick vm_object_lock(object); 38145748Smckusick } 38248386Skarels first_m = NULL; 38345748Smckusick 38445748Smckusick vm_page_zero_fill(m); 38550911Smckusick cnt.v_zfod++; 38656920Shibler m->flags &= ~PG_FAKE; 38745748Smckusick break; 38845748Smckusick } 38945748Smckusick else { 39045748Smckusick vm_object_lock(next_object); 39145748Smckusick if (object != first_object) 39245748Smckusick object->paging_in_progress--; 39345748Smckusick vm_object_unlock(object); 39445748Smckusick object = next_object; 39545748Smckusick object->paging_in_progress++; 39645748Smckusick } 39745748Smckusick } 39845748Smckusick 39956920Shibler if ((m->flags & (PG_ACTIVE | PG_INACTIVE | PG_BUSY)) != PG_BUSY) 40056920Shibler panic("vm_fault: active, inactive or !busy after main loop"); 40145748Smckusick 40245748Smckusick /* 40345748Smckusick * PAGE HAS BEEN FOUND. 40445748Smckusick * [Loop invariant still holds -- the object lock 40545748Smckusick * is held.] 40645748Smckusick */ 40745748Smckusick 40845748Smckusick old_m = m; /* save page that would be copied */ 40945748Smckusick 41045748Smckusick /* 41145748Smckusick * If the page is being written, but isn't 41245748Smckusick * already owned by the top-level object, 41345748Smckusick * we have to copy it into a new page owned 41445748Smckusick * by the top-level object. 41545748Smckusick */ 41645748Smckusick 41745748Smckusick if (object != first_object) { 41845748Smckusick /* 41945748Smckusick * We only really need to copy if we 42045748Smckusick * want to write it. 42145748Smckusick */ 42245748Smckusick 42345748Smckusick if (fault_type & VM_PROT_WRITE) { 42445748Smckusick 42545748Smckusick /* 42645748Smckusick * If we try to collapse first_object at this 42745748Smckusick * point, we may deadlock when we try to get 42845748Smckusick * the lock on an intermediate object (since we 42945748Smckusick * have the bottom object locked). We can't 43045748Smckusick * unlock the bottom object, because the page 43145748Smckusick * we found may move (by collapse) if we do. 43245748Smckusick * 43345748Smckusick * Instead, we first copy the page. Then, when 43445748Smckusick * we have no more use for the bottom object, 43545748Smckusick * we unlock it and try to collapse. 43645748Smckusick * 43745748Smckusick * Note that we copy the page even if we didn't 43845748Smckusick * need to... that's the breaks. 43945748Smckusick */ 44045748Smckusick 44145748Smckusick /* 44245748Smckusick * We already have an empty page in 44345748Smckusick * first_object - use it. 44445748Smckusick */ 44545748Smckusick 44645748Smckusick vm_page_copy(m, first_m); 44756920Shibler first_m->flags &= ~PG_FAKE; 44845748Smckusick 44945748Smckusick /* 45045748Smckusick * If another map is truly sharing this 45145748Smckusick * page with us, we have to flush all 45245748Smckusick * uses of the original page, since we 45345748Smckusick * can't distinguish those which want the 45445748Smckusick * original from those which need the 45545748Smckusick * new copy. 45649288Shibler * 45749288Shibler * XXX If we know that only one map has 45849288Shibler * access to this page, then we could 45949288Shibler * avoid the pmap_page_protect() call. 46045748Smckusick */ 46145748Smckusick 46245748Smckusick vm_page_lock_queues(); 46352904Smckusick vm_page_activate(m); 46464692Shibler vm_page_deactivate(m); 46549288Shibler pmap_page_protect(VM_PAGE_TO_PHYS(m), VM_PROT_NONE); 46645748Smckusick vm_page_unlock_queues(); 46745748Smckusick 46845748Smckusick /* 46945748Smckusick * We no longer need the old page or object. 47045748Smckusick */ 47145748Smckusick PAGE_WAKEUP(m); 47245748Smckusick object->paging_in_progress--; 47345748Smckusick vm_object_unlock(object); 47445748Smckusick 47545748Smckusick /* 47645748Smckusick * Only use the new page below... 47745748Smckusick */ 47845748Smckusick 47950911Smckusick cnt.v_cow_faults++; 48045748Smckusick m = first_m; 48145748Smckusick object = first_object; 48245748Smckusick offset = first_offset; 48345748Smckusick 48445748Smckusick /* 48545748Smckusick * Now that we've gotten the copy out of the 48645748Smckusick * way, let's try to collapse the top object. 48745748Smckusick */ 48845748Smckusick vm_object_lock(object); 48945748Smckusick /* 49045748Smckusick * But we have to play ugly games with 49145748Smckusick * paging_in_progress to do that... 49245748Smckusick */ 49345748Smckusick object->paging_in_progress--; 49445748Smckusick vm_object_collapse(object); 49545748Smckusick object->paging_in_progress++; 49645748Smckusick } 49745748Smckusick else { 49865684Shibler prot &= ~VM_PROT_WRITE; 49956382Smckusick m->flags |= PG_COPYONWRITE; 50045748Smckusick } 50145748Smckusick } 50245748Smckusick 50356920Shibler if (m->flags & (PG_ACTIVE|PG_INACTIVE)) 50445748Smckusick panic("vm_fault: active or inactive before copy object handling"); 50545748Smckusick 50645748Smckusick /* 50745748Smckusick * If the page is being written, but hasn't been 50845748Smckusick * copied to the copy-object, we have to copy it there. 50945748Smckusick */ 51045748Smckusick RetryCopy: 51148386Skarels if (first_object->copy != NULL) { 51248386Skarels vm_object_t copy_object = first_object->copy; 51348386Skarels vm_offset_t copy_offset; 51448386Skarels vm_page_t copy_m; 51545748Smckusick 51645748Smckusick /* 51745748Smckusick * We only need to copy if we want to write it. 51845748Smckusick */ 51945748Smckusick if ((fault_type & VM_PROT_WRITE) == 0) { 52045748Smckusick prot &= ~VM_PROT_WRITE; 52156382Smckusick m->flags |= PG_COPYONWRITE; 52245748Smckusick } 52345748Smckusick else { 52445748Smckusick /* 52545748Smckusick * Try to get the lock on the copy_object. 52645748Smckusick */ 52745748Smckusick if (!vm_object_lock_try(copy_object)) { 52845748Smckusick vm_object_unlock(object); 52945748Smckusick /* should spin a bit here... */ 53045748Smckusick vm_object_lock(object); 53145748Smckusick goto RetryCopy; 53245748Smckusick } 53345748Smckusick 53445748Smckusick /* 53545748Smckusick * Make another reference to the copy-object, 53645748Smckusick * to keep it from disappearing during the 53745748Smckusick * copy. 53845748Smckusick */ 53945748Smckusick copy_object->ref_count++; 54045748Smckusick 54145748Smckusick /* 54245748Smckusick * Does the page exist in the copy? 54345748Smckusick */ 54445748Smckusick copy_offset = first_offset 54545748Smckusick - copy_object->shadow_offset; 54645748Smckusick copy_m = vm_page_lookup(copy_object, copy_offset); 54748386Skarels if (page_exists = (copy_m != NULL)) { 54856382Smckusick if (copy_m->flags & PG_BUSY) { 54945748Smckusick #ifdef DOTHREADS 55045748Smckusick int wait_result; 55145748Smckusick 55245748Smckusick /* 55345748Smckusick * If the page is being brought 55445748Smckusick * in, wait for it and then retry. 55545748Smckusick */ 55645748Smckusick PAGE_ASSERT_WAIT(copy_m, !change_wiring); 55745748Smckusick RELEASE_PAGE(m); 55845748Smckusick copy_object->ref_count--; 55945748Smckusick vm_object_unlock(copy_object); 56045748Smckusick UNLOCK_THINGS; 56145748Smckusick thread_block(); 56245748Smckusick wait_result = current_thread()->wait_result; 56345748Smckusick vm_object_deallocate(first_object); 56445748Smckusick if (wait_result != THREAD_AWAKENED) 56545748Smckusick return(KERN_SUCCESS); 56645748Smckusick goto RetryFault; 56745748Smckusick #else 56845748Smckusick /* 56945748Smckusick * If the page is being brought 57045748Smckusick * in, wait for it and then retry. 57145748Smckusick */ 57245748Smckusick PAGE_ASSERT_WAIT(copy_m, !change_wiring); 57345748Smckusick RELEASE_PAGE(m); 57445748Smckusick copy_object->ref_count--; 57545748Smckusick vm_object_unlock(copy_object); 57645748Smckusick UNLOCK_THINGS; 57745748Smckusick thread_block(); 57845748Smckusick vm_object_deallocate(first_object); 57945748Smckusick goto RetryFault; 58045748Smckusick #endif 58145748Smckusick } 58245748Smckusick } 58345748Smckusick 58445748Smckusick /* 58545748Smckusick * If the page is not in memory (in the object) 58645748Smckusick * and the object has a pager, we have to check 58745748Smckusick * if the pager has the data in secondary 58845748Smckusick * storage. 58945748Smckusick */ 59045748Smckusick if (!page_exists) { 59145748Smckusick 59245748Smckusick /* 59345748Smckusick * If we don't allocate a (blank) page 59445748Smckusick * here... another thread could try 59545748Smckusick * to page it in, allocate a page, and 59645748Smckusick * then block on the busy page in its 59745748Smckusick * shadow (first_object). Then we'd 59845748Smckusick * trip over the busy page after we 59945748Smckusick * found that the copy_object's pager 60045748Smckusick * doesn't have the page... 60145748Smckusick */ 60245748Smckusick copy_m = vm_page_alloc(copy_object, 60345748Smckusick copy_offset); 60448386Skarels if (copy_m == NULL) { 60545748Smckusick /* 60645748Smckusick * Wait for a page, then retry. 60745748Smckusick */ 60845748Smckusick RELEASE_PAGE(m); 60945748Smckusick copy_object->ref_count--; 61045748Smckusick vm_object_unlock(copy_object); 61145748Smckusick UNLOCK_AND_DEALLOCATE; 61245748Smckusick VM_WAIT; 61345748Smckusick goto RetryFault; 61445748Smckusick } 61545748Smckusick 61648386Skarels if (copy_object->pager != NULL) { 61745748Smckusick vm_object_unlock(object); 61845748Smckusick vm_object_unlock(copy_object); 61945748Smckusick UNLOCK_MAP; 62045748Smckusick 62145748Smckusick page_exists = vm_pager_has_page( 62245748Smckusick copy_object->pager, 62345748Smckusick (copy_offset + copy_object->paging_offset)); 62445748Smckusick 62545748Smckusick vm_object_lock(copy_object); 62645748Smckusick 62745748Smckusick /* 62845748Smckusick * Since the map is unlocked, someone 62945748Smckusick * else could have copied this object 63045748Smckusick * and put a different copy_object 63145748Smckusick * between the two. Or, the last 63245748Smckusick * reference to the copy-object (other 63345748Smckusick * than the one we have) may have 63445748Smckusick * disappeared - if that has happened, 63545748Smckusick * we don't need to make the copy. 63645748Smckusick */ 63745748Smckusick if (copy_object->shadow != object || 63845748Smckusick copy_object->ref_count == 1) { 63945748Smckusick /* 64045748Smckusick * Gaah... start over! 64145748Smckusick */ 64245748Smckusick FREE_PAGE(copy_m); 64345748Smckusick vm_object_unlock(copy_object); 64445748Smckusick vm_object_deallocate(copy_object); 64545748Smckusick /* may block */ 64645748Smckusick vm_object_lock(object); 64745748Smckusick goto RetryCopy; 64845748Smckusick } 64945748Smckusick vm_object_lock(object); 65045748Smckusick 65145748Smckusick if (page_exists) { 65245748Smckusick /* 65345748Smckusick * We didn't need the page 65445748Smckusick */ 65545748Smckusick FREE_PAGE(copy_m); 65645748Smckusick } 65745748Smckusick } 65845748Smckusick } 65945748Smckusick if (!page_exists) { 66045748Smckusick /* 66145748Smckusick * Must copy page into copy-object. 66245748Smckusick */ 66345748Smckusick vm_page_copy(m, copy_m); 66456920Shibler copy_m->flags &= ~PG_FAKE; 66545748Smckusick 66645748Smckusick /* 66745748Smckusick * Things to remember: 66845748Smckusick * 1. The copied page must be marked 'dirty' 66945748Smckusick * so it will be paged out to the copy 67045748Smckusick * object. 67145748Smckusick * 2. If the old page was in use by any users 67245748Smckusick * of the copy-object, it must be removed 67345748Smckusick * from all pmaps. (We can't know which 67445748Smckusick * pmaps use it.) 67545748Smckusick */ 67645748Smckusick vm_page_lock_queues(); 67749288Shibler pmap_page_protect(VM_PAGE_TO_PHYS(old_m), 67849288Shibler VM_PROT_NONE); 67956382Smckusick copy_m->flags &= ~PG_CLEAN; 68045748Smckusick vm_page_activate(copy_m); /* XXX */ 68145748Smckusick vm_page_unlock_queues(); 68245748Smckusick 68345748Smckusick PAGE_WAKEUP(copy_m); 68445748Smckusick } 68545748Smckusick /* 68645748Smckusick * The reference count on copy_object must be 68745748Smckusick * at least 2: one for our extra reference, 68845748Smckusick * and at least one from the outside world 68945748Smckusick * (we checked that when we last locked 69045748Smckusick * copy_object). 69145748Smckusick */ 69245748Smckusick copy_object->ref_count--; 69345748Smckusick vm_object_unlock(copy_object); 69456382Smckusick m->flags &= ~PG_COPYONWRITE; 69545748Smckusick } 69645748Smckusick } 69745748Smckusick 69856382Smckusick if (m->flags & (PG_ACTIVE | PG_INACTIVE)) 69945748Smckusick panic("vm_fault: active or inactive before retrying lookup"); 70045748Smckusick 70145748Smckusick /* 70245748Smckusick * We must verify that the maps have not changed 70345748Smckusick * since our last lookup. 70445748Smckusick */ 70545748Smckusick 70645748Smckusick if (!lookup_still_valid) { 70745748Smckusick vm_object_t retry_object; 70845748Smckusick vm_offset_t retry_offset; 70945748Smckusick vm_prot_t retry_prot; 71045748Smckusick 71145748Smckusick /* 71245748Smckusick * Since map entries may be pageable, make sure we can 71345748Smckusick * take a page fault on them. 71445748Smckusick */ 71545748Smckusick vm_object_unlock(object); 71645748Smckusick 71745748Smckusick /* 71845748Smckusick * To avoid trying to write_lock the map while another 71945748Smckusick * thread has it read_locked (in vm_map_pageable), we 72045748Smckusick * do not try for write permission. If the page is 72145748Smckusick * still writable, we will get write permission. If it 72245748Smckusick * is not, or has been marked needs_copy, we enter the 72345748Smckusick * mapping without write permission, and will merely 72445748Smckusick * take another fault. 72545748Smckusick */ 72645748Smckusick result = vm_map_lookup(&map, vaddr, 72745748Smckusick fault_type & ~VM_PROT_WRITE, &entry, 72845748Smckusick &retry_object, &retry_offset, &retry_prot, 72945748Smckusick &wired, &su); 73045748Smckusick 73145748Smckusick vm_object_lock(object); 73245748Smckusick 73345748Smckusick /* 73445748Smckusick * If we don't need the page any longer, put it on the 73545748Smckusick * active list (the easiest thing to do here). If no 73645748Smckusick * one needs it, pageout will grab it eventually. 73745748Smckusick */ 73845748Smckusick 73945748Smckusick if (result != KERN_SUCCESS) { 74045748Smckusick RELEASE_PAGE(m); 74145748Smckusick UNLOCK_AND_DEALLOCATE; 74245748Smckusick return(result); 74345748Smckusick } 74445748Smckusick 74545748Smckusick lookup_still_valid = TRUE; 74645748Smckusick 74745748Smckusick if ((retry_object != first_object) || 74845748Smckusick (retry_offset != first_offset)) { 74945748Smckusick RELEASE_PAGE(m); 75045748Smckusick UNLOCK_AND_DEALLOCATE; 75145748Smckusick goto RetryFault; 75245748Smckusick } 75345748Smckusick 75445748Smckusick /* 75545748Smckusick * Check whether the protection has changed or the object 75645748Smckusick * has been copied while we left the map unlocked. 75745748Smckusick * Changing from read to write permission is OK - we leave 75845748Smckusick * the page write-protected, and catch the write fault. 75945748Smckusick * Changing from write to read permission means that we 76045748Smckusick * can't mark the page write-enabled after all. 76145748Smckusick */ 76245748Smckusick prot &= retry_prot; 76356382Smckusick if (m->flags & PG_COPYONWRITE) 76445748Smckusick prot &= ~VM_PROT_WRITE; 76545748Smckusick } 76645748Smckusick 76745748Smckusick /* 76845748Smckusick * (the various bits we're fiddling with here are locked by 76945748Smckusick * the object's lock) 77045748Smckusick */ 77145748Smckusick 77245748Smckusick /* XXX This distorts the meaning of the copy_on_write bit */ 77345748Smckusick 77445748Smckusick if (prot & VM_PROT_WRITE) 77556382Smckusick m->flags &= ~PG_COPYONWRITE; 77645748Smckusick 77745748Smckusick /* 77845748Smckusick * It's critically important that a wired-down page be faulted 77945748Smckusick * only once in each map for which it is wired. 78045748Smckusick */ 78145748Smckusick 78256382Smckusick if (m->flags & (PG_ACTIVE | PG_INACTIVE)) 78345748Smckusick panic("vm_fault: active or inactive before pmap_enter"); 78445748Smckusick 78545748Smckusick vm_object_unlock(object); 78645748Smckusick 78745748Smckusick /* 78845748Smckusick * Put this page into the physical map. 78945748Smckusick * We had to do the unlock above because pmap_enter 79045748Smckusick * may cause other faults. We don't put the 79145748Smckusick * page back on the active queue until later so 79245748Smckusick * that the page-out daemon won't find us (yet). 79345748Smckusick */ 79445748Smckusick 79556920Shibler pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), prot, wired); 79645748Smckusick 79745748Smckusick /* 79845748Smckusick * If the page is not wired down, then put it where the 79945748Smckusick * pageout daemon can find it. 80045748Smckusick */ 80145748Smckusick vm_object_lock(object); 80245748Smckusick vm_page_lock_queues(); 80345748Smckusick if (change_wiring) { 80445748Smckusick if (wired) 80545748Smckusick vm_page_wire(m); 80645748Smckusick else 80745748Smckusick vm_page_unwire(m); 80845748Smckusick } 80945748Smckusick else 81045748Smckusick vm_page_activate(m); 81145748Smckusick vm_page_unlock_queues(); 81245748Smckusick 81345748Smckusick /* 81445748Smckusick * Unlock everything, and return 81545748Smckusick */ 81645748Smckusick 81745748Smckusick PAGE_WAKEUP(m); 81845748Smckusick UNLOCK_AND_DEALLOCATE; 81945748Smckusick 82045748Smckusick return(KERN_SUCCESS); 82145748Smckusick 82245748Smckusick } 82345748Smckusick 82445748Smckusick /* 82545748Smckusick * vm_fault_wire: 82645748Smckusick * 82745748Smckusick * Wire down a range of virtual addresses in a map. 82845748Smckusick */ 82958597Shibler int 83058597Shibler vm_fault_wire(map, start, end) 83145748Smckusick vm_map_t map; 83245748Smckusick vm_offset_t start, end; 83345748Smckusick { 83445748Smckusick register vm_offset_t va; 83545748Smckusick register pmap_t pmap; 83658597Shibler int rv; 83745748Smckusick 83845748Smckusick pmap = vm_map_pmap(map); 83945748Smckusick 84045748Smckusick /* 84145748Smckusick * Inform the physical mapping system that the 84245748Smckusick * range of addresses may not fault, so that 84345748Smckusick * page tables and such can be locked down as well. 84445748Smckusick */ 84545748Smckusick 84645748Smckusick pmap_pageable(pmap, start, end, FALSE); 84745748Smckusick 84845748Smckusick /* 84945748Smckusick * We simulate a fault to get the page and enter it 85045748Smckusick * in the physical map. 85145748Smckusick */ 85245748Smckusick 85345748Smckusick for (va = start; va < end; va += PAGE_SIZE) { 85458597Shibler rv = vm_fault(map, va, VM_PROT_NONE, TRUE); 85558597Shibler if (rv) { 85658597Shibler if (va != start) 85758597Shibler vm_fault_unwire(map, start, va); 85858597Shibler return(rv); 85958597Shibler } 86045748Smckusick } 86158597Shibler return(KERN_SUCCESS); 86245748Smckusick } 86345748Smckusick 86445748Smckusick 86545748Smckusick /* 86645748Smckusick * vm_fault_unwire: 86745748Smckusick * 86845748Smckusick * Unwire a range of virtual addresses in a map. 86945748Smckusick */ 870*68164Scgd void 871*68164Scgd vm_fault_unwire(map, start, end) 87245748Smckusick vm_map_t map; 87345748Smckusick vm_offset_t start, end; 87445748Smckusick { 87545748Smckusick 87645748Smckusick register vm_offset_t va, pa; 87745748Smckusick register pmap_t pmap; 87845748Smckusick 87945748Smckusick pmap = vm_map_pmap(map); 88045748Smckusick 88145748Smckusick /* 88245748Smckusick * Since the pages are wired down, we must be able to 88345748Smckusick * get their mappings from the physical map system. 88445748Smckusick */ 88545748Smckusick 88645748Smckusick vm_page_lock_queues(); 88745748Smckusick 88845748Smckusick for (va = start; va < end; va += PAGE_SIZE) { 88945748Smckusick pa = pmap_extract(pmap, va); 89045748Smckusick if (pa == (vm_offset_t) 0) { 89145748Smckusick panic("unwire: page not in pmap"); 89245748Smckusick } 89345748Smckusick pmap_change_wiring(pmap, va, FALSE); 89445748Smckusick vm_page_unwire(PHYS_TO_VM_PAGE(pa)); 89545748Smckusick } 89645748Smckusick vm_page_unlock_queues(); 89745748Smckusick 89845748Smckusick /* 89945748Smckusick * Inform the physical mapping system that the range 90045748Smckusick * of addresses may fault, so that page tables and 90145748Smckusick * such may be unwired themselves. 90245748Smckusick */ 90345748Smckusick 90445748Smckusick pmap_pageable(pmap, start, end, TRUE); 90545748Smckusick 90645748Smckusick } 90745748Smckusick 90845748Smckusick /* 90945748Smckusick * Routine: 91045748Smckusick * vm_fault_copy_entry 91145748Smckusick * Function: 91245748Smckusick * Copy all of the pages from a wired-down map entry to another. 91345748Smckusick * 91445748Smckusick * In/out conditions: 91545748Smckusick * The source and destination maps must be locked for write. 91645748Smckusick * The source map entry must be wired down (or be a sharing map 91745748Smckusick * entry corresponding to a main map entry that is wired down). 91845748Smckusick */ 91945748Smckusick 920*68164Scgd void 921*68164Scgd vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry) 92245748Smckusick vm_map_t dst_map; 92345748Smckusick vm_map_t src_map; 92445748Smckusick vm_map_entry_t dst_entry; 92545748Smckusick vm_map_entry_t src_entry; 92645748Smckusick { 92745748Smckusick 92845748Smckusick vm_object_t dst_object; 92945748Smckusick vm_object_t src_object; 93045748Smckusick vm_offset_t dst_offset; 93145748Smckusick vm_offset_t src_offset; 93245748Smckusick vm_prot_t prot; 93345748Smckusick vm_offset_t vaddr; 93445748Smckusick vm_page_t dst_m; 93545748Smckusick vm_page_t src_m; 93645748Smckusick 93745748Smckusick #ifdef lint 93845748Smckusick src_map++; 93960345Storek #endif 94045748Smckusick 94145748Smckusick src_object = src_entry->object.vm_object; 94245748Smckusick src_offset = src_entry->offset; 94345748Smckusick 94445748Smckusick /* 94545748Smckusick * Create the top-level object for the destination entry. 94645748Smckusick * (Doesn't actually shadow anything - we copy the pages 94745748Smckusick * directly.) 94845748Smckusick */ 94945748Smckusick dst_object = vm_object_allocate( 95045748Smckusick (vm_size_t) (dst_entry->end - dst_entry->start)); 95145748Smckusick 95245748Smckusick dst_entry->object.vm_object = dst_object; 95345748Smckusick dst_entry->offset = 0; 95445748Smckusick 95545748Smckusick prot = dst_entry->max_protection; 95645748Smckusick 95745748Smckusick /* 95845748Smckusick * Loop through all of the pages in the entry's range, copying 95945748Smckusick * each one from the source object (it should be there) to the 96045748Smckusick * destination object. 96145748Smckusick */ 96245748Smckusick for (vaddr = dst_entry->start, dst_offset = 0; 96345748Smckusick vaddr < dst_entry->end; 96445748Smckusick vaddr += PAGE_SIZE, dst_offset += PAGE_SIZE) { 96545748Smckusick 96645748Smckusick /* 96745748Smckusick * Allocate a page in the destination object 96845748Smckusick */ 96945748Smckusick vm_object_lock(dst_object); 97045748Smckusick do { 97145748Smckusick dst_m = vm_page_alloc(dst_object, dst_offset); 97248386Skarels if (dst_m == NULL) { 97345748Smckusick vm_object_unlock(dst_object); 97445748Smckusick VM_WAIT; 97545748Smckusick vm_object_lock(dst_object); 97645748Smckusick } 97748386Skarels } while (dst_m == NULL); 97845748Smckusick 97945748Smckusick /* 98045748Smckusick * Find the page in the source object, and copy it in. 98145748Smckusick * (Because the source is wired down, the page will be 98245748Smckusick * in memory.) 98345748Smckusick */ 98445748Smckusick vm_object_lock(src_object); 98545748Smckusick src_m = vm_page_lookup(src_object, dst_offset + src_offset); 98648386Skarels if (src_m == NULL) 98745748Smckusick panic("vm_fault_copy_wired: page missing"); 98845748Smckusick 98945748Smckusick vm_page_copy(src_m, dst_m); 99045748Smckusick 99145748Smckusick /* 99245748Smckusick * Enter it in the pmap... 99345748Smckusick */ 99445748Smckusick vm_object_unlock(src_object); 99545748Smckusick vm_object_unlock(dst_object); 99645748Smckusick 99745748Smckusick pmap_enter(dst_map->pmap, vaddr, VM_PAGE_TO_PHYS(dst_m), 99845748Smckusick prot, FALSE); 99945748Smckusick 100045748Smckusick /* 100145748Smckusick * Mark it no longer busy, and put it on the active list. 100245748Smckusick */ 100345748Smckusick vm_object_lock(dst_object); 100445748Smckusick vm_page_lock_queues(); 100545748Smckusick vm_page_activate(dst_m); 100645748Smckusick vm_page_unlock_queues(); 100745748Smckusick PAGE_WAKEUP(dst_m); 100845748Smckusick vm_object_unlock(dst_object); 100945748Smckusick } 101045748Smckusick 101145748Smckusick } 1012