|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: vm_fault.c ! 54: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 55: * ! 56: * Page fault handling module. ! 57: */ ! 58: #ifdef MACH_BSD ! 59: /* remove after component interface available */ ! 60: extern int vnode_pager_workaround; ! 61: #endif ! 62: ! 63: #include <mach_cluster_stats.h> ! 64: #include <mach_pagemap.h> ! 65: #include <mach_kdb.h> ! 66: ! 67: #include <vm/vm_fault.h> ! 68: #include <mach/kern_return.h> ! 69: #include <mach/message.h> /* for error codes */ ! 70: #include <kern/host_statistics.h> ! 71: #include <kern/counters.h> ! 72: #include <kern/task.h> ! 73: #include <kern/thread.h> ! 74: #include <kern/sched_prim.h> ! 75: #include <kern/host.h> ! 76: #include <kern/xpr.h> ! 77: #include <vm/vm_map.h> ! 78: #include <vm/vm_object.h> ! 79: #include <vm/vm_page.h> ! 80: #include <vm/pmap.h> ! 81: #include <vm/vm_pageout.h> ! 82: #include <mach/vm_param.h> ! 83: #include <mach/vm_behavior.h> ! 84: #include <mach/memory_object.h> ! 85: /* For memory_object_data_{request,unlock} */ ! 86: #include <kern/mach_param.h> ! 87: #include <kern/macro_help.h> ! 88: #include <kern/zalloc.h> ! 89: #include <kern/misc_protos.h> ! 90: ! 91: #include <sys/kdebug.h> ! 92: ! 93: #define VM_FAULT_CLASSIFY 0 ! 94: #define VM_FAULT_STATIC_CONFIG 1 ! 95: ! 96: #define TRACEFAULTPAGE 0 /* (TEST/DEBUG) */ ! 97: ! 98: int vm_object_absent_max = 50; ! 99: ! 100: int vm_fault_debug = 0; ! 101: boolean_t vm_page_deactivate_behind = TRUE; ! 102: ! 103: vm_machine_attribute_val_t mv_cache_sync = MATTR_VAL_CACHE_SYNC; ! 104: ! 105: #if !VM_FAULT_STATIC_CONFIG ! 106: boolean_t vm_fault_dirty_handling = FALSE; ! 107: boolean_t vm_fault_interruptible = FALSE; ! 108: boolean_t software_reference_bits = TRUE; ! 109: #endif ! 110: ! 111: #if MACH_KDB ! 112: extern struct db_watchpoint *db_watchpoint_list; ! 113: #endif /* MACH_KDB */ ! 114: ! 115: /* Forward declarations of internal routines. */ ! 116: extern kern_return_t vm_fault_wire_fast( ! 117: vm_map_t map, ! 118: vm_offset_t va, ! 119: vm_map_entry_t entry); ! 120: ! 121: extern void vm_fault_continue(void); ! 122: ! 123: extern void vm_fault_copy_cleanup( ! 124: vm_page_t page, ! 125: vm_page_t top_page); ! 126: ! 127: extern void vm_fault_copy_dst_cleanup( ! 128: vm_page_t page); ! 129: ! 130: #if VM_FAULT_CLASSIFY ! 131: extern void vm_fault_classify(vm_object_t object, ! 132: vm_offset_t offset, ! 133: vm_prot_t fault_type); ! 134: ! 135: extern void vm_fault_classify_init(void); ! 136: #endif ! 137: ! 138: /* ! 139: * Routine: vm_fault_init ! 140: * Purpose: ! 141: * Initialize our private data structures. ! 142: */ ! 143: void ! 144: vm_fault_init(void) ! 145: { ! 146: } ! 147: ! 148: /* ! 149: * Routine: vm_fault_cleanup ! 150: * Purpose: ! 151: * Clean up the result of vm_fault_page. ! 152: * Results: ! 153: * The paging reference for "object" is released. ! 154: * "object" is unlocked. ! 155: * If "top_page" is not null, "top_page" is ! 156: * freed and the paging reference for the object ! 157: * containing it is released. ! 158: * ! 159: * In/out conditions: ! 160: * "object" must be locked. ! 161: */ ! 162: void ! 163: vm_fault_cleanup( ! 164: register vm_object_t object, ! 165: register vm_page_t top_page) ! 166: { ! 167: vm_object_paging_end(object); ! 168: vm_object_unlock(object); ! 169: ! 170: if (top_page != VM_PAGE_NULL) { ! 171: object = top_page->object; ! 172: vm_object_lock(object); ! 173: VM_PAGE_FREE(top_page); ! 174: vm_object_paging_end(object); ! 175: vm_object_unlock(object); ! 176: } ! 177: } ! 178: ! 179: #if MACH_CLUSTER_STATS ! 180: #define MAXCLUSTERPAGES 16 ! 181: struct { ! 182: unsigned long pages_in_cluster; ! 183: unsigned long pages_at_higher_offsets; ! 184: unsigned long pages_at_lower_offsets; ! 185: } cluster_stats_in[MAXCLUSTERPAGES]; ! 186: #define CLUSTER_STAT(clause) clause ! 187: #define CLUSTER_STAT_HIGHER(x) \ ! 188: ((cluster_stats_in[(x)].pages_at_higher_offsets)++) ! 189: #define CLUSTER_STAT_LOWER(x) \ ! 190: ((cluster_stats_in[(x)].pages_at_lower_offsets)++) ! 191: #define CLUSTER_STAT_CLUSTER(x) \ ! 192: ((cluster_stats_in[(x)].pages_in_cluster)++) ! 193: #else /* MACH_CLUSTER_STATS */ ! 194: #define CLUSTER_STAT(clause) ! 195: #endif /* MACH_CLUSTER_STATS */ ! 196: ! 197: /* XXX - temporary */ ! 198: boolean_t vm_allow_clustered_pagein = FALSE; ! 199: int vm_pagein_cluster_used = 0; ! 200: ! 201: /* ! 202: * Prepage default sizes given VM_BEHAVIOR_DEFAULT reference behavior ! 203: */ ! 204: int vm_default_ahead = 1; /* Number of pages to prepage ahead */ ! 205: int vm_default_behind = 0; /* Number of pages to prepage behind */ ! 206: ! 207: #define ALIGNED(x) (((x) & (PAGE_SIZE - 1)) == 0) ! 208: ! 209: /* ! 210: * Routine: vm_fault_page ! 211: * Purpose: ! 212: * Find the resident page for the virtual memory ! 213: * specified by the given virtual memory object ! 214: * and offset. ! 215: * Additional arguments: ! 216: * The required permissions for the page is given ! 217: * in "fault_type". Desired permissions are included ! 218: * in "protection". The minimum and maximum valid offsets ! 219: * within the object for the relevant map entry are ! 220: * passed in "lo_offset" and "hi_offset" respectively and ! 221: * the expected page reference pattern is passed in "behavior". ! 222: * These three parameters are used to determine pagein cluster ! 223: * limits. ! 224: * ! 225: * If the desired page is known to be resident (for ! 226: * example, because it was previously wired down), asserting ! 227: * the "unwiring" parameter will speed the search. ! 228: * ! 229: * If the operation can be interrupted (by thread_abort ! 230: * or thread_terminate), then the "interruptible" ! 231: * parameter should be asserted. ! 232: * ! 233: * Results: ! 234: * The page containing the proper data is returned ! 235: * in "result_page". ! 236: * ! 237: * In/out conditions: ! 238: * The source object must be locked and referenced, ! 239: * and must donate one paging reference. The reference ! 240: * is not affected. The paging reference and lock are ! 241: * consumed. ! 242: * ! 243: * If the call succeeds, the object in which "result_page" ! 244: * resides is left locked and holding a paging reference. ! 245: * If this is not the original object, a busy page in the ! 246: * original object is returned in "top_page", to prevent other ! 247: * callers from pursuing this same data, along with a paging ! 248: * reference for the original object. The "top_page" should ! 249: * be destroyed when this guarantee is no longer required. ! 250: * The "result_page" is also left busy. It is not removed ! 251: * from the pageout queues. ! 252: */ ! 253: ! 254: vm_fault_return_t ! 255: vm_fault_page( ! 256: /* Arguments: */ ! 257: vm_object_t first_object, /* Object to begin search */ ! 258: vm_offset_t first_offset, /* Offset into object */ ! 259: vm_prot_t fault_type, /* What access is requested */ ! 260: boolean_t must_be_resident,/* Must page be resident? */ ! 261: int interruptible, /* how may fault be interrupted? */ ! 262: vm_offset_t lo_offset, /* Map entry start */ ! 263: vm_offset_t hi_offset, /* Map entry end */ ! 264: vm_behavior_t behavior, /* Page reference behavior */ ! 265: /* Modifies in place: */ ! 266: vm_prot_t *protection, /* Protection for mapping */ ! 267: /* Returns: */ ! 268: vm_page_t *result_page, /* Page found, if successful */ ! 269: vm_page_t *top_page, /* Page in top object, if ! 270: * not result_page. */ ! 271: int *type_of_fault, /* if non-null, fill in with type of fault ! 272: * COW, zero-fill, etc... returned in trace point */ ! 273: /* More arguments: */ ! 274: kern_return_t *error_code, /* code if page is in error */ ! 275: boolean_t no_zero_fill, /* don't zero fill absent pages */ ! 276: boolean_t data_supply) /* treat as data_supply if ! 277: * it is a write fault and a full ! 278: * page is provided */ ! 279: { ! 280: register ! 281: vm_page_t m; ! 282: register ! 283: vm_object_t object; ! 284: register ! 285: vm_offset_t offset; ! 286: vm_page_t first_m; ! 287: vm_object_t next_object; ! 288: vm_object_t copy_object; ! 289: boolean_t look_for_page; ! 290: vm_prot_t access_required = fault_type; ! 291: vm_prot_t wants_copy_flag; ! 292: thread_t thread = current_thread(); ! 293: vm_size_t cluster_size, length; ! 294: vm_offset_t cluster_offset; ! 295: vm_offset_t cluster_start, cluster_end, paging_offset; ! 296: vm_offset_t align_offset; ! 297: CLUSTER_STAT(int pages_at_higher_offsets;) ! 298: CLUSTER_STAT(int pages_at_lower_offsets;) ! 299: #ifdef MACH_BSD ! 300: kern_return_t vnode_pager_data_request( ! 301: ipc_port_t, ipc_port_t, vm_offset_t, vm_size_t, vm_prot_t); ! 302: #endif ! 303: ! 304: #if MACH_PAGEMAP ! 305: /* ! 306: * MACH page map - an optional optimization where a bit map is maintained ! 307: * by the VM subsystem for internal objects to indicate which pages of ! 308: * the object currently reside on backing store. This existence map ! 309: * duplicates information maintained by the vnode pager. It is ! 310: * created at the time of the first pageout against the object, i.e. ! 311: * at the same time pager for the object is created. The optimization ! 312: * is designed to eliminate pager interaction overhead, if it is ! 313: * 'known' that the page does not exist on backing store. ! 314: * ! 315: * LOOK_FOR() evaluates to TRUE if the page specified by object/offset is ! 316: * either marked as paged out in the existence map for the object or no ! 317: * existence map exists for the object. LOOK_FOR() is one of the ! 318: * criteria in the decision to invoke the pager. It is also used as one ! 319: * of the criteria to terminate the scan for adjacent pages in a clustered ! 320: * pagein operation. Note that LOOK_FOR() always evaluates to TRUE for ! 321: * permanent objects. Note also that if the pager for an internal object ! 322: * has not been created, the pager is not invoked regardless of the value ! 323: * of LOOK_FOR() and that clustered pagein scans are only done on an object ! 324: * for which a pager has been created. ! 325: * ! 326: * PAGED_OUT() evaluates to TRUE if the page specified by the object/offset ! 327: * is marked as paged out in the existence map for the object. PAGED_OUT() ! 328: * PAGED_OUT() is used to determine if a page has already been pushed ! 329: * into a copy object in order to avoid a redundant page out operation. ! 330: */ ! 331: #define LOOK_FOR(o, f) (vm_external_state_get((o)->existence_map, (f)) \ ! 332: != VM_EXTERNAL_STATE_ABSENT) ! 333: #define PAGED_OUT(o, f) (vm_external_state_get((o)->existence_map, (f)) \ ! 334: == VM_EXTERNAL_STATE_EXISTS) ! 335: #else /* MACH_PAGEMAP */ ! 336: /* ! 337: * If the MACH page map optimization is not enabled, ! 338: * LOOK_FOR() always evaluates to TRUE. The pager will always be ! 339: * invoked to resolve missing pages in an object, assuming the pager ! 340: * has been created for the object. In a clustered page operation, the ! 341: * absence of a page on backing backing store cannot be used to terminate ! 342: * a scan for adjacent pages since that information is available only in ! 343: * the pager. Hence pages that may not be paged out are potentially ! 344: * included in a clustered request. The vnode pager is coded to deal ! 345: * with any combination of absent/present pages in a clustered ! 346: * pagein request. PAGED_OUT() always evaluates to FALSE, i.e. the pager ! 347: * will always be invoked to push a dirty page into a copy object assuming ! 348: * a pager has been created. If the page has already been pushed, the ! 349: * pager will ingore the new request. ! 350: */ ! 351: #define LOOK_FOR(o, f) TRUE ! 352: #define PAGED_OUT(o, f) FALSE ! 353: #endif /* MACH_PAGEMAP */ ! 354: ! 355: /* ! 356: * Recovery actions ! 357: */ ! 358: #define PREPARE_RELEASE_PAGE(m) \ ! 359: MACRO_BEGIN \ ! 360: vm_page_lock_queues(); \ ! 361: MACRO_END ! 362: ! 363: #define DO_RELEASE_PAGE(m) \ ! 364: MACRO_BEGIN \ ! 365: PAGE_WAKEUP_DONE(m); \ ! 366: if (!m->active && !m->inactive) \ ! 367: vm_page_activate(m); \ ! 368: vm_page_unlock_queues(); \ ! 369: MACRO_END ! 370: ! 371: #define RELEASE_PAGE(m) \ ! 372: MACRO_BEGIN \ ! 373: PREPARE_RELEASE_PAGE(m); \ ! 374: DO_RELEASE_PAGE(m); \ ! 375: MACRO_END ! 376: ! 377: #if TRACEFAULTPAGE ! 378: dbgTrace(0xBEEF0002, (unsigned int) first_object, (unsigned int) first_offset); /* (TEST/DEBUG) */ ! 379: #endif ! 380: ! 381: ! 382: ! 383: #if !VM_FAULT_STATIC_CONFIG ! 384: if (vm_fault_dirty_handling ! 385: #if MACH_KDB ! 386: /* ! 387: * If there are watchpoints set, then ! 388: * we don't want to give away write permission ! 389: * on a read fault. Make the task write fault, ! 390: * so that the watchpoint code notices the access. ! 391: */ ! 392: || db_watchpoint_list ! 393: #endif /* MACH_KDB */ ! 394: ) { ! 395: /* ! 396: * If we aren't asking for write permission, ! 397: * then don't give it away. We're using write ! 398: * faults to set the dirty bit. ! 399: */ ! 400: if (!(fault_type & VM_PROT_WRITE)) ! 401: *protection &= ~VM_PROT_WRITE; ! 402: } ! 403: ! 404: if (!vm_fault_interruptible) ! 405: interruptible = THREAD_UNINT; ! 406: #else /* STATIC_CONFIG */ ! 407: #if MACH_KDB ! 408: /* ! 409: * If there are watchpoints set, then ! 410: * we don't want to give away write permission ! 411: * on a read fault. Make the task write fault, ! 412: * so that the watchpoint code notices the access. ! 413: */ ! 414: if (db_watchpoint_list) { ! 415: /* ! 416: * If we aren't asking for write permission, ! 417: * then don't give it away. We're using write ! 418: * faults to set the dirty bit. ! 419: */ ! 420: if (!(fault_type & VM_PROT_WRITE)) ! 421: *protection &= ~VM_PROT_WRITE; ! 422: } ! 423: ! 424: interruptible = THREAD_UNINT; /* vm_fault_interruptible */ ! 425: #endif /* MACH_KDB */ ! 426: #endif /* STATIC_CONFIG */ ! 427: ! 428: /* ! 429: * INVARIANTS (through entire routine): ! 430: * ! 431: * 1) At all times, we must either have the object ! 432: * lock or a busy page in some object to prevent ! 433: * some other thread from trying to bring in ! 434: * the same page. ! 435: * ! 436: * Note that we cannot hold any locks during the ! 437: * pager access or when waiting for memory, so ! 438: * we use a busy page then. ! 439: * ! 440: * Note also that we aren't as concerned about more than ! 441: * one thread attempting to memory_object_data_unlock ! 442: * the same page at once, so we don't hold the page ! 443: * as busy then, but do record the highest unlock ! 444: * value so far. [Unlock requests may also be delivered ! 445: * out of order.] ! 446: * ! 447: * 2) To prevent another thread from racing us down the ! 448: * shadow chain and entering a new page in the top ! 449: * object before we do, we must keep a busy page in ! 450: * the top object while following the shadow chain. ! 451: * ! 452: * 3) We must increment paging_in_progress on any object ! 453: * for which we have a busy page, to prevent ! 454: * vm_object_collapse from removing the busy page ! 455: * without our noticing. ! 456: * ! 457: * 4) We leave busy pages on the pageout queues. ! 458: * If the pageout daemon comes across a busy page, ! 459: * it will remove the page from the pageout queues. ! 460: */ ! 461: ! 462: /* ! 463: * Search for the page at object/offset. ! 464: */ ! 465: ! 466: object = first_object; ! 467: offset = first_offset; ! 468: first_m = VM_PAGE_NULL; ! 469: access_required = fault_type; ! 470: ! 471: XPR(XPR_VM_FAULT, ! 472: "vm_f_page: obj 0x%X, offset 0x%X, type %d, prot %d\n", ! 473: (integer_t)object, offset, fault_type, *protection, 0); ! 474: ! 475: /* ! 476: * See whether this page is resident ! 477: */ ! 478: ! 479: while (TRUE) { ! 480: #if TRACEFAULTPAGE ! 481: dbgTrace(0xBEEF0003, (unsigned int) 0, (unsigned int) 0); /* (TEST/DEBUG) */ ! 482: #endif ! 483: if (!object->alive) { ! 484: vm_fault_cleanup(object, first_m); ! 485: return(VM_FAULT_MEMORY_ERROR); ! 486: } ! 487: m = vm_page_lookup(object, offset); ! 488: #if TRACEFAULTPAGE ! 489: dbgTrace(0xBEEF0004, (unsigned int) m, (unsigned int) object); /* (TEST/DEBUG) */ ! 490: #endif ! 491: if (m != VM_PAGE_NULL) { ! 492: /* ! 493: * If the page was pre-paged as part of a ! 494: * cluster, record the fact. ! 495: */ ! 496: if (m->clustered) { ! 497: vm_pagein_cluster_used++; ! 498: m->clustered = FALSE; ! 499: } ! 500: ! 501: /* ! 502: * If the page is being brought in, ! 503: * wait for it and then retry. ! 504: * ! 505: * A possible optimization: if the page ! 506: * is known to be resident, we can ignore ! 507: * pages that are absent (regardless of ! 508: * whether they're busy). ! 509: */ ! 510: ! 511: if (m->busy) { ! 512: kern_return_t wait_result; ! 513: ! 514: #if TRACEFAULTPAGE ! 515: dbgTrace(0xBEEF0005, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ ! 516: #endif ! 517: PAGE_ASSERT_WAIT(m, interruptible); ! 518: vm_object_unlock(object); ! 519: XPR(XPR_VM_FAULT, ! 520: "vm_f_page: block busy obj 0x%X, offset 0x%X, page 0x%X\n", ! 521: (integer_t)object, offset, ! 522: (integer_t)m, 0, 0); ! 523: counter(c_vm_fault_page_block_busy_kernel++); ! 524: thread_block((void (*)(void))0); ! 525: ! 526: wait_result = thread->wait_result; ! 527: vm_object_lock(object); ! 528: if (wait_result != THREAD_AWAKENED) { ! 529: vm_fault_cleanup(object, first_m); ! 530: if (wait_result == THREAD_RESTART) ! 531: { ! 532: return(VM_FAULT_RETRY); ! 533: } ! 534: else ! 535: { ! 536: return(VM_FAULT_INTERRUPTED); ! 537: } ! 538: } ! 539: continue; ! 540: } ! 541: ! 542: /* ! 543: * If the page is in error, give up now. ! 544: */ ! 545: ! 546: if (m->error) { ! 547: #if TRACEFAULTPAGE ! 548: dbgTrace(0xBEEF0006, (unsigned int) m, (unsigned int) error_code); /* (TEST/DEBUG) */ ! 549: #endif ! 550: if (error_code) ! 551: *error_code = m->page_error; ! 552: VM_PAGE_FREE(m); ! 553: vm_fault_cleanup(object, first_m); ! 554: ! 555: return(VM_FAULT_MEMORY_ERROR); ! 556: } ! 557: ! 558: /* ! 559: * If the pager wants us to restart ! 560: * at the top of the chain, ! 561: * typically because it has moved the ! 562: * page to another pager, then do so. ! 563: */ ! 564: ! 565: if (m->restart) { ! 566: #if TRACEFAULTPAGE ! 567: dbgTrace(0xBEEF0007, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ ! 568: #endif ! 569: VM_PAGE_FREE(m); ! 570: vm_fault_cleanup(object, first_m); ! 571: ! 572: return(VM_FAULT_RETRY); ! 573: } ! 574: ! 575: /* ! 576: * If the page isn't busy, but is absent, ! 577: * then it was deemed "unavailable". ! 578: */ ! 579: ! 580: if (m->absent) { ! 581: /* ! 582: * Remove the non-existent page (unless it's ! 583: * in the top object) and move on down to the ! 584: * next object (if there is one). ! 585: */ ! 586: #if TRACEFAULTPAGE ! 587: dbgTrace(0xBEEF0008, (unsigned int) m, (unsigned int) object->shadow); /* (TEST/DEBUG) */ ! 588: #endif ! 589: ! 590: next_object = object->shadow; ! 591: if (next_object == VM_OBJECT_NULL) { ! 592: vm_page_t real_m; ! 593: ! 594: assert(!must_be_resident); ! 595: ! 596: /* ! 597: * Absent page at bottom of shadow ! 598: * chain; zero fill the page we left ! 599: * busy in the first object, and flush ! 600: * the absent page. But first we ! 601: * need to allocate a real page. ! 602: */ ! 603: if ((vm_page_free_target - ! 604: ((vm_page_free_target ! 605: -vm_page_free_min)>>2)) ! 606: > vm_page_free_count) { ! 607: assert(object->ref_count > 0); ! 608: vm_fault_cleanup( ! 609: object, first_m); ! 610: /* kick off pageout daemon */ ! 611: vm_page_wait(); ! 612: if ((m = vm_page_grab()) ! 613: != VM_PAGE_NULL) { ! 614: /* need to kick off */ ! 615: /* other parties */ ! 616: /* waiting on free */ ! 617: /* pages */ ! 618: VM_PAGE_FREE(m); ! 619: } ! 620: return VM_FAULT_RETRY; ! 621: } ! 622: ! 623: real_m = vm_page_grab(); ! 624: if (real_m == VM_PAGE_NULL) { ! 625: vm_fault_cleanup(object, first_m); ! 626: return(VM_FAULT_MEMORY_SHORTAGE); ! 627: } ! 628: ! 629: XPR(XPR_VM_FAULT, ! 630: "vm_f_page: zero obj 0x%X, off 0x%X, page 0x%X, first_obj 0x%X\n", ! 631: (integer_t)object, offset, ! 632: (integer_t)m, ! 633: (integer_t)first_object, 0); ! 634: if (object != first_object) { ! 635: VM_PAGE_FREE(m); ! 636: vm_object_paging_end(object); ! 637: vm_object_unlock(object); ! 638: object = first_object; ! 639: offset = first_offset; ! 640: m = first_m; ! 641: first_m = VM_PAGE_NULL; ! 642: vm_object_lock(object); ! 643: } ! 644: ! 645: VM_PAGE_FREE(m); ! 646: assert(real_m->busy); ! 647: vm_page_insert(real_m, object, offset); ! 648: m = real_m; ! 649: ! 650: /* ! 651: * Drop the lock while zero filling ! 652: * page. Then break because this ! 653: * is the page we wanted. Checking ! 654: * the page lock is a waste of time; ! 655: * this page was either absent or ! 656: * newly allocated -- in both cases ! 657: * it can't be page locked by a pager. ! 658: */ ! 659: if (!no_zero_fill) { ! 660: vm_object_unlock(object); ! 661: vm_page_zero_fill(m); ! 662: if (type_of_fault) ! 663: *type_of_fault = DBG_ZERO_FILL_FAULT; ! 664: VM_STAT(zero_fill_count++); ! 665: vm_object_lock(object); ! 666: } ! 667: pmap_clear_modify(m->phys_addr); ! 668: vm_page_lock_queues(); ! 669: VM_PAGE_QUEUES_REMOVE(m); ! 670: queue_enter(&vm_page_queue_inactive, ! 671: m, vm_page_t, pageq); ! 672: m->inactive = TRUE; ! 673: vm_page_inactive_count++; ! 674: vm_page_unlock_queues(); ! 675: break; ! 676: } else { ! 677: if (must_be_resident) { ! 678: vm_object_paging_end(object); ! 679: } else if (object != first_object) { ! 680: vm_object_paging_end(object); ! 681: VM_PAGE_FREE(m); ! 682: } else { ! 683: first_m = m; ! 684: m->absent = FALSE; ! 685: m->unusual = FALSE; ! 686: vm_object_absent_release(object); ! 687: m->busy = TRUE; ! 688: ! 689: vm_page_lock_queues(); ! 690: VM_PAGE_QUEUES_REMOVE(m); ! 691: vm_page_unlock_queues(); ! 692: } ! 693: XPR(XPR_VM_FAULT, ! 694: "vm_f_page: unavail obj 0x%X, off 0x%X, next_obj 0x%X, newoff 0x%X\n", ! 695: (integer_t)object, offset, ! 696: (integer_t)next_object, ! 697: offset+object->shadow_offset,0); ! 698: offset += object->shadow_offset; ! 699: hi_offset += object->shadow_offset; ! 700: lo_offset += object->shadow_offset; ! 701: access_required = VM_PROT_READ; ! 702: vm_object_lock(next_object); ! 703: vm_object_unlock(object); ! 704: object = next_object; ! 705: vm_object_paging_begin(object); ! 706: continue; ! 707: } ! 708: } ! 709: ! 710: if ((m->cleaning) ! 711: && ((object != first_object) || ! 712: (object->copy != VM_OBJECT_NULL)) ! 713: && (fault_type & VM_PROT_WRITE)) { ! 714: /* ! 715: * This is a copy-on-write fault that will ! 716: * cause us to revoke access to this page, but ! 717: * this page is in the process of being cleaned ! 718: * in a clustered pageout. We must wait until ! 719: * the cleaning operation completes before ! 720: * revoking access to the original page, ! 721: * otherwise we might attempt to remove a ! 722: * wired mapping. ! 723: */ ! 724: #if TRACEFAULTPAGE ! 725: dbgTrace(0xBEEF0009, (unsigned int) m, (unsigned int) offset); /* (TEST/DEBUG) */ ! 726: #endif ! 727: XPR(XPR_VM_FAULT, ! 728: "vm_f_page: cleaning obj 0x%X, offset 0x%X, page 0x%X\n", ! 729: (integer_t)object, offset, ! 730: (integer_t)m, 0, 0); ! 731: /* take an extra ref so that object won't die */ ! 732: assert(object->ref_count > 0); ! 733: object->ref_count++; ! 734: vm_object_res_reference(object); ! 735: vm_fault_cleanup(object, first_m); ! 736: counter(c_vm_fault_page_block_backoff_kernel++); ! 737: vm_object_lock(object); ! 738: assert(object->ref_count > 0); ! 739: m = vm_page_lookup(object, offset); ! 740: if (m != VM_PAGE_NULL && m->cleaning) { ! 741: PAGE_ASSERT_WAIT(m, interruptible); ! 742: vm_object_unlock(object); ! 743: thread_block((void (*)(void)) 0); ! 744: vm_object_deallocate(object); ! 745: goto backoff; ! 746: } else { ! 747: vm_object_unlock(object); ! 748: vm_object_deallocate(object); ! 749: return VM_FAULT_RETRY; ! 750: } ! 751: } ! 752: ! 753: /* ! 754: * If the desired access to this page has ! 755: * been locked out, request that it be unlocked. ! 756: */ ! 757: ! 758: if (access_required & m->page_lock) { ! 759: if ((access_required & m->unlock_request) != access_required) { ! 760: vm_prot_t new_unlock_request; ! 761: kern_return_t rc; ! 762: ! 763: #if TRACEFAULTPAGE ! 764: dbgTrace(0xBEEF000A, (unsigned int) m, (unsigned int) object->pager_ready); /* (TEST/DEBUG) */ ! 765: #endif ! 766: if (!object->pager_ready) { ! 767: XPR(XPR_VM_FAULT, ! 768: "vm_f_page: ready wait acc_req %d, obj 0x%X, offset 0x%X, page 0x%X\n", ! 769: access_required, ! 770: (integer_t)object, offset, ! 771: (integer_t)m, 0); ! 772: /* take an extra ref */ ! 773: assert(object->ref_count > 0); ! 774: object->ref_count++; ! 775: vm_object_res_reference(object); ! 776: vm_fault_cleanup(object, ! 777: first_m); ! 778: counter(c_vm_fault_page_block_backoff_kernel++); ! 779: vm_object_lock(object); ! 780: assert(object->ref_count > 0); ! 781: if (!object->pager_ready) { ! 782: vm_object_assert_wait( ! 783: object, ! 784: VM_OBJECT_EVENT_PAGER_READY, ! 785: interruptible); ! 786: vm_object_unlock(object); ! 787: thread_block((void (*)(void))0); ! 788: vm_object_deallocate(object); ! 789: goto backoff; ! 790: } else { ! 791: vm_object_unlock(object); ! 792: vm_object_deallocate(object); ! 793: return VM_FAULT_RETRY; ! 794: } ! 795: } ! 796: ! 797: new_unlock_request = m->unlock_request = ! 798: (access_required | m->unlock_request); ! 799: vm_object_unlock(object); ! 800: XPR(XPR_VM_FAULT, ! 801: "vm_f_page: unlock obj 0x%X, offset 0x%X, page 0x%X, unl_req %d\n", ! 802: (integer_t)object, offset, ! 803: (integer_t)m, new_unlock_request, 0); ! 804: if ((rc = memory_object_data_unlock( ! 805: object->pager, ! 806: object->pager_request, ! 807: offset + object->paging_offset, ! 808: PAGE_SIZE, ! 809: new_unlock_request)) ! 810: != KERN_SUCCESS) { ! 811: if (vm_fault_debug) ! 812: printf("vm_fault: memory_object_data_unlock failed\n"); ! 813: vm_object_lock(object); ! 814: vm_fault_cleanup(object, first_m); ! 815: ! 816: return((rc == MACH_SEND_INTERRUPTED) ? ! 817: VM_FAULT_INTERRUPTED : ! 818: VM_FAULT_MEMORY_ERROR); ! 819: } ! 820: vm_object_lock(object); ! 821: continue; ! 822: } ! 823: ! 824: XPR(XPR_VM_FAULT, ! 825: "vm_f_page: access wait acc_req %d, obj 0x%X, offset 0x%X, page 0x%X\n", ! 826: access_required, (integer_t)object, ! 827: offset, (integer_t)m, 0); ! 828: /* take an extra ref so object won't die */ ! 829: assert(object->ref_count > 0); ! 830: object->ref_count++; ! 831: vm_object_res_reference(object); ! 832: vm_fault_cleanup(object, first_m); ! 833: counter(c_vm_fault_page_block_backoff_kernel++); ! 834: vm_object_lock(object); ! 835: assert(object->ref_count > 0); ! 836: m = vm_page_lookup(object, offset); ! 837: if (m != VM_PAGE_NULL && ! 838: (access_required & m->page_lock) && ! 839: !((access_required & m->unlock_request) != access_required)) { ! 840: PAGE_ASSERT_WAIT(m, interruptible); ! 841: vm_object_unlock(object); ! 842: thread_block((void (*)(void)) 0); ! 843: vm_object_deallocate(object); ! 844: goto backoff; ! 845: } else { ! 846: vm_object_unlock(object); ! 847: vm_object_deallocate(object); ! 848: return VM_FAULT_RETRY; ! 849: } ! 850: } ! 851: /* ! 852: * We mark the page busy and leave it on ! 853: * the pageout queues. If the pageout ! 854: * deamon comes across it, then it will ! 855: * remove the page. ! 856: */ ! 857: ! 858: #if TRACEFAULTPAGE ! 859: dbgTrace(0xBEEF000B, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ ! 860: #endif ! 861: ! 862: #if !VM_FAULT_STATIC_CONFIG ! 863: if (!software_reference_bits) { ! 864: vm_page_lock_queues(); ! 865: if (m->inactive) ! 866: vm_stat.reactivations++; ! 867: ! 868: VM_PAGE_QUEUES_REMOVE(m); ! 869: vm_page_unlock_queues(); ! 870: } ! 871: #endif ! 872: XPR(XPR_VM_FAULT, ! 873: "vm_f_page: found page obj 0x%X, offset 0x%X, page 0x%X\n", ! 874: (integer_t)object, offset, (integer_t)m, 0, 0); ! 875: assert(!m->busy); ! 876: m->busy = TRUE; ! 877: assert(!m->absent); ! 878: break; ! 879: } ! 880: ! 881: look_for_page = ! 882: (object->pager_created) && ! 883: LOOK_FOR(object, offset) && ! 884: (!data_supply); ! 885: ! 886: #if TRACEFAULTPAGE ! 887: dbgTrace(0xBEEF000C, (unsigned int) look_for_page, (unsigned int) object); /* (TEST/DEBUG) */ ! 888: #endif ! 889: if ((look_for_page || (object == first_object)) ! 890: && !must_be_resident) { ! 891: /* ! 892: * Allocate a new page for this object/offset ! 893: * pair. ! 894: */ ! 895: ! 896: m = vm_page_grab_fictitious(); ! 897: #if TRACEFAULTPAGE ! 898: dbgTrace(0xBEEF000D, (unsigned int) m, (unsigned int) object); /* (TEST/DEBUG) */ ! 899: #endif ! 900: if (m == VM_PAGE_NULL) { ! 901: vm_fault_cleanup(object, first_m); ! 902: return(VM_FAULT_FICTITIOUS_SHORTAGE); ! 903: } ! 904: vm_page_insert(m, object, offset); ! 905: } ! 906: ! 907: if (look_for_page && !must_be_resident) { ! 908: kern_return_t rc; ! 909: ! 910: /* ! 911: * If the memory manager is not ready, we ! 912: * cannot make requests. ! 913: */ ! 914: if (!object->pager_ready) { ! 915: #if TRACEFAULTPAGE ! 916: dbgTrace(0xBEEF000E, (unsigned int) 0, (unsigned int) 0); /* (TEST/DEBUG) */ ! 917: #endif ! 918: VM_PAGE_FREE(m); ! 919: XPR(XPR_VM_FAULT, ! 920: "vm_f_page: ready wait obj 0x%X, offset 0x%X\n", ! 921: (integer_t)object, offset, 0, 0, 0); ! 922: /* take an extra ref so object won't die */ ! 923: assert(object->ref_count > 0); ! 924: object->ref_count++; ! 925: vm_object_res_reference(object); ! 926: vm_fault_cleanup(object, first_m); ! 927: counter(c_vm_fault_page_block_backoff_kernel++); ! 928: vm_object_lock(object); ! 929: assert(object->ref_count > 0); ! 930: if (!object->pager_ready) { ! 931: vm_object_assert_wait(object, ! 932: VM_OBJECT_EVENT_PAGER_READY, ! 933: interruptible); ! 934: vm_object_unlock(object); ! 935: thread_block((void (*)(void))0); ! 936: vm_object_deallocate(object); ! 937: goto backoff; ! 938: } else { ! 939: vm_object_unlock(object); ! 940: vm_object_deallocate(object); ! 941: return VM_FAULT_RETRY; ! 942: } ! 943: } ! 944: ! 945: if (object->internal) { ! 946: /* ! 947: * Requests to the default pager ! 948: * must reserve a real page in advance, ! 949: * because the pager's data-provided ! 950: * won't block for pages. IMPORTANT: ! 951: * this acts as a throttling mechanism ! 952: * for data_requests to the default ! 953: * pager. ! 954: */ ! 955: ! 956: #if TRACEFAULTPAGE ! 957: dbgTrace(0xBEEF000F, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ ! 958: #endif ! 959: if (m->fictitious && !vm_page_convert(m)) { ! 960: VM_PAGE_FREE(m); ! 961: vm_fault_cleanup(object, first_m); ! 962: return(VM_FAULT_MEMORY_SHORTAGE); ! 963: } ! 964: } else if (object->absent_count > ! 965: vm_object_absent_max) { ! 966: /* ! 967: * If there are too many outstanding page ! 968: * requests pending on this object, we ! 969: * wait for them to be resolved now. ! 970: */ ! 971: ! 972: #if TRACEFAULTPAGE ! 973: dbgTrace(0xBEEF0010, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ ! 974: #endif ! 975: VM_PAGE_FREE(m); ! 976: /* take an extra ref so object won't die */ ! 977: assert(object->ref_count > 0); ! 978: object->ref_count++; ! 979: vm_object_res_reference(object); ! 980: vm_fault_cleanup(object, first_m); ! 981: counter(c_vm_fault_page_block_backoff_kernel++); ! 982: vm_object_lock(object); ! 983: assert(object->ref_count > 0); ! 984: if (object->absent_count > vm_object_absent_max) { ! 985: vm_object_absent_assert_wait(object, ! 986: interruptible); ! 987: vm_object_unlock(object); ! 988: thread_block((void (*)(void))0); ! 989: vm_object_deallocate(object); ! 990: goto backoff; ! 991: } else { ! 992: vm_object_unlock(object); ! 993: vm_object_deallocate(object); ! 994: return VM_FAULT_RETRY; ! 995: } ! 996: } ! 997: ! 998: /* ! 999: * Indicate that the page is waiting for data ! 1000: * from the memory manager. ! 1001: */ ! 1002: ! 1003: m->list_req_pending = TRUE; ! 1004: m->absent = TRUE; ! 1005: m->unusual = TRUE; ! 1006: object->absent_count++; ! 1007: ! 1008: cluster_start = offset; ! 1009: length = PAGE_SIZE; ! 1010: cluster_size = object->cluster_size; ! 1011: ! 1012: /* ! 1013: * Skip clustered pagein if it is globally disabled ! 1014: * or random page reference behavior is expected ! 1015: * for the address range containing the faulting ! 1016: * address or the object paging block size is ! 1017: * equal to the page size. ! 1018: */ ! 1019: if (!vm_allow_clustered_pagein || ! 1020: behavior == VM_BEHAVIOR_RANDOM || ! 1021: cluster_size == PAGE_SIZE) ! 1022: goto no_clustering; ! 1023: ! 1024: assert(offset >= lo_offset); ! 1025: assert(offset < hi_offset); ! 1026: assert(ALIGNED(object->paging_offset)); ! 1027: assert(cluster_size >= PAGE_SIZE); ! 1028: ! 1029: #if TRACEFAULTPAGE ! 1030: dbgTrace(0xBEEF0011, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ ! 1031: #endif ! 1032: /* ! 1033: * Decide whether to scan ahead or behind for ! 1034: * additional pages contiguous to the faulted ! 1035: * page in the same paging block. The decision ! 1036: * is based on system wide globals and the ! 1037: * expected page reference behavior of the ! 1038: * address range contained the faulting address. ! 1039: * First calculate some constants. ! 1040: */ ! 1041: paging_offset = offset + object->paging_offset; ! 1042: cluster_offset = paging_offset & (cluster_size - 1); ! 1043: align_offset = paging_offset&(PAGE_SIZE-1); ! 1044: if (align_offset != 0) { ! 1045: cluster_offset = trunc_page(cluster_offset); ! 1046: } ! 1047: ! 1048: #define SPANS_CLUSTER(x) ((((x) - align_offset) & (cluster_size - 1)) == 0) ! 1049: ! 1050: /* ! 1051: * Backward scan only if reverse sequential ! 1052: * behavior has been specified ! 1053: */ ! 1054: CLUSTER_STAT(pages_at_lower_offsets = 0;) ! 1055: if (((vm_default_behind != 0 && ! 1056: behavior == VM_BEHAVIOR_DEFAULT) || ! 1057: behavior == VM_BEHAVIOR_RSEQNTL) && offset) { ! 1058: vm_offset_t cluster_bot; ! 1059: ! 1060: /* ! 1061: * Calculate lower search boundary. ! 1062: * Exclude pages that span a cluster boundary. ! 1063: * Clip to start of map entry. ! 1064: * For default page reference behavior, scan ! 1065: * default pages behind. ! 1066: */ ! 1067: cluster_bot = (offset > cluster_offset) ? ! 1068: offset - cluster_offset : offset; ! 1069: if (align_offset != 0) { ! 1070: if ((cluster_bot < offset) && ! 1071: SPANS_CLUSTER(cluster_bot)) { ! 1072: cluster_bot += PAGE_SIZE; ! 1073: } ! 1074: } ! 1075: if (behavior == VM_BEHAVIOR_DEFAULT) { ! 1076: vm_offset_t bot = vm_default_behind*PAGE_SIZE; ! 1077: ! 1078: if (cluster_bot < (offset - bot)) ! 1079: cluster_bot = offset - bot; ! 1080: } ! 1081: if (lo_offset > cluster_bot) ! 1082: cluster_bot = lo_offset; ! 1083: ! 1084: for ( cluster_start = offset - PAGE_SIZE; ! 1085: (cluster_start >= cluster_bot) && ! 1086: (cluster_start != (align_offset - PAGE_SIZE)); ! 1087: cluster_start -= PAGE_SIZE) { ! 1088: assert(cluster_size > PAGE_SIZE); ! 1089: retry_cluster_backw: ! 1090: if (!LOOK_FOR(object, cluster_start) || ! 1091: vm_page_lookup(object, cluster_start) ! 1092: != VM_PAGE_NULL) { ! 1093: break; ! 1094: } ! 1095: if (object->internal) { ! 1096: /* ! 1097: * need to acquire a real page in ! 1098: * advance because this acts as ! 1099: * a throttling mechanism for ! 1100: * data_requests to the default ! 1101: * pager. If this fails, give up ! 1102: * trying to find any more pages ! 1103: * in the cluster and send off the ! 1104: * request for what we already have. ! 1105: */ ! 1106: if ((m = vm_page_grab()) ! 1107: == VM_PAGE_NULL) { ! 1108: cluster_start += PAGE_SIZE; ! 1109: cluster_end = offset + PAGE_SIZE; ! 1110: goto give_up; ! 1111: } ! 1112: } else if ((m = vm_page_grab_fictitious()) ! 1113: == VM_PAGE_NULL) { ! 1114: vm_object_unlock(object); ! 1115: vm_page_more_fictitious(); ! 1116: vm_object_lock(object); ! 1117: goto retry_cluster_backw; ! 1118: } ! 1119: m->absent = TRUE; ! 1120: m->unusual = TRUE; ! 1121: m->clustered = TRUE; ! 1122: m->list_req_pending = TRUE; ! 1123: ! 1124: vm_page_insert(m, object, cluster_start); ! 1125: CLUSTER_STAT(pages_at_lower_offsets++;) ! 1126: object->absent_count++; ! 1127: } ! 1128: cluster_start += PAGE_SIZE; ! 1129: assert(cluster_start >= cluster_bot); ! 1130: } ! 1131: assert(cluster_start <= offset); ! 1132: ! 1133: /* ! 1134: * Forward scan if default or sequential behavior ! 1135: * specified ! 1136: */ ! 1137: CLUSTER_STAT(pages_at_higher_offsets = 0;) ! 1138: if ((behavior == VM_BEHAVIOR_DEFAULT && ! 1139: vm_default_ahead != 0) || ! 1140: behavior == VM_BEHAVIOR_SEQUENTIAL) { ! 1141: vm_offset_t cluster_top; ! 1142: ! 1143: /* ! 1144: * Calculate upper search boundary. ! 1145: * Exclude pages that span a cluster boundary. ! 1146: * Clip to end of map entry. ! 1147: * For default page reference behavior, scan ! 1148: * default pages ahead. ! 1149: */ ! 1150: cluster_top = (offset + cluster_size) - ! 1151: cluster_offset; ! 1152: if (align_offset != 0) { ! 1153: if ((cluster_top > (offset + PAGE_SIZE)) && ! 1154: SPANS_CLUSTER(cluster_top)) { ! 1155: cluster_top -= PAGE_SIZE; ! 1156: } ! 1157: } ! 1158: if (behavior == VM_BEHAVIOR_DEFAULT) { ! 1159: vm_offset_t top = (vm_default_ahead*PAGE_SIZE)+ ! 1160: PAGE_SIZE; ! 1161: ! 1162: if (cluster_top > (offset + top)) ! 1163: cluster_top = offset + top; ! 1164: } ! 1165: if (cluster_top > hi_offset) ! 1166: cluster_top = hi_offset; ! 1167: ! 1168: for (cluster_end = offset + PAGE_SIZE; ! 1169: cluster_end < cluster_top; ! 1170: cluster_end += PAGE_SIZE) { ! 1171: assert(cluster_size > PAGE_SIZE); ! 1172: retry_cluster_forw: ! 1173: if (!LOOK_FOR(object, cluster_end) || ! 1174: vm_page_lookup(object, cluster_end) ! 1175: != VM_PAGE_NULL) { ! 1176: break; ! 1177: } ! 1178: if (object->internal) { ! 1179: /* ! 1180: * need to acquire a real page in ! 1181: * advance because this acts as ! 1182: * a throttling mechanism for ! 1183: * data_requests to the default ! 1184: * pager. If this fails, give up ! 1185: * trying to find any more pages ! 1186: * in the cluster and send off the ! 1187: * request for what we already have. ! 1188: */ ! 1189: if ((m = vm_page_grab()) ! 1190: == VM_PAGE_NULL) { ! 1191: break; ! 1192: } ! 1193: } else if ((m = vm_page_grab_fictitious()) ! 1194: == VM_PAGE_NULL) { ! 1195: vm_object_unlock(object); ! 1196: vm_page_more_fictitious(); ! 1197: vm_object_lock(object); ! 1198: goto retry_cluster_forw; ! 1199: } ! 1200: m->absent = TRUE; ! 1201: m->unusual = TRUE; ! 1202: m->clustered = TRUE; ! 1203: m->list_req_pending = TRUE; ! 1204: ! 1205: vm_page_insert(m, object, cluster_end); ! 1206: CLUSTER_STAT(pages_at_higher_offsets++;) ! 1207: object->absent_count++; ! 1208: } ! 1209: assert(cluster_end <= cluster_top); ! 1210: } ! 1211: else { ! 1212: cluster_end = offset + PAGE_SIZE; ! 1213: } ! 1214: give_up: ! 1215: assert(cluster_end >= offset + PAGE_SIZE); ! 1216: length = cluster_end - cluster_start; ! 1217: ! 1218: #if MACH_CLUSTER_STATS ! 1219: CLUSTER_STAT_HIGHER(pages_at_higher_offsets); ! 1220: CLUSTER_STAT_LOWER(pages_at_lower_offsets); ! 1221: CLUSTER_STAT_CLUSTER(length/PAGE_SIZE); ! 1222: #endif /* MACH_CLUSTER_STATS */ ! 1223: ! 1224: no_clustering: ! 1225: #if TRACEFAULTPAGE ! 1226: dbgTrace(0xBEEF0012, (unsigned int) object, (unsigned int) 0); /* (TEST/DEBUG) */ ! 1227: #endif ! 1228: /* ! 1229: * We have a busy page, so we can ! 1230: * release the object lock. ! 1231: */ ! 1232: vm_object_unlock(object); ! 1233: ! 1234: /* ! 1235: * Call the memory manager to retrieve the data. ! 1236: */ ! 1237: ! 1238: if (type_of_fault) ! 1239: *type_of_fault = DBG_PAGEIN_FAULT; ! 1240: VM_STAT(pageins++); ! 1241: current_task()->pageins++; ! 1242: ! 1243: /* ! 1244: * If this object uses a copy_call strategy, ! 1245: * and we are interested in a copy of this object ! 1246: * (having gotten here only by following a ! 1247: * shadow chain), then tell the memory manager ! 1248: * via a flag added to the desired_access ! 1249: * parameter, so that it can detect a race ! 1250: * between our walking down the shadow chain ! 1251: * and its pushing pages up into a copy of ! 1252: * the object that it manages. ! 1253: */ ! 1254: ! 1255: if (object->copy_strategy == MEMORY_OBJECT_COPY_CALL && ! 1256: object != first_object) { ! 1257: wants_copy_flag = VM_PROT_WANTS_COPY; ! 1258: } else { ! 1259: wants_copy_flag = VM_PROT_NONE; ! 1260: } ! 1261: ! 1262: XPR(XPR_VM_FAULT, ! 1263: "vm_f_page: data_req obj 0x%X, offset 0x%X, page 0x%X, acc %d\n", ! 1264: (integer_t)object, offset, (integer_t)m, ! 1265: access_required | wants_copy_flag, 0); ! 1266: ! 1267: #ifdef MACH_BSD ! 1268: if (((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) == ! 1269: ((rpc_subsystem_t) &vnode_pager_workaround)) { ! 1270: rc = vnode_pager_data_request(object->pager, ! 1271: object->pager_request, ! 1272: cluster_start + object->paging_offset, ! 1273: length, ! 1274: access_required | wants_copy_flag); ! 1275: } else { ! 1276: rc = memory_object_data_request(object->pager, ! 1277: object->pager_request, ! 1278: cluster_start + object->paging_offset, ! 1279: length, ! 1280: access_required | wants_copy_flag); ! 1281: } ! 1282: #else ! 1283: rc = memory_object_data_request(object->pager, ! 1284: object->pager_request, ! 1285: cluster_start + object->paging_offset, ! 1286: length, ! 1287: access_required | wants_copy_flag); ! 1288: ! 1289: #endif ! 1290: ! 1291: #if TRACEFAULTPAGE ! 1292: dbgTrace(0xBEEF0013, (unsigned int) object, (unsigned int) rc); /* (TEST/DEBUG) */ ! 1293: #endif ! 1294: if (rc != KERN_SUCCESS) { ! 1295: if (rc != MACH_SEND_INTERRUPTED ! 1296: && vm_fault_debug) ! 1297: printf("%s(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) failed, rc=%d, object=0x%x\n", ! 1298: "memory_object_data_request", ! 1299: object->pager, ! 1300: object->pager_request, ! 1301: cluster_start + object->paging_offset, ! 1302: length, access_required, ! 1303: rc, object); ! 1304: /* ! 1305: * Don't want to leave a busy page around, ! 1306: * but the data request may have blocked, ! 1307: * so check if it's still there and busy. ! 1308: */ ! 1309: vm_object_lock(object); ! 1310: for (; length; ! 1311: length -= PAGE_SIZE, ! 1312: cluster_start += PAGE_SIZE) { ! 1313: vm_page_t p; ! 1314: if ((p = vm_page_lookup(object, ! 1315: cluster_start)) ! 1316: && p->absent && p->busy ! 1317: && p != first_m) { ! 1318: VM_PAGE_FREE(m); ! 1319: } ! 1320: } ! 1321: vm_fault_cleanup(object, first_m); ! 1322: ! 1323: return((rc == MACH_SEND_INTERRUPTED) ? ! 1324: VM_FAULT_INTERRUPTED : ! 1325: VM_FAULT_MEMORY_ERROR); ! 1326: } ! 1327: ! 1328: /* ! 1329: * Retry with same object/offset, since new data may ! 1330: * be in a different page (i.e., m is meaningless at ! 1331: * this point). ! 1332: */ ! 1333: vm_object_lock(object); ! 1334: continue; ! 1335: } ! 1336: ! 1337: /* ! 1338: * The only case in which we get here is if ! 1339: * object has no pager (or unwiring). If the pager doesn't ! 1340: * have the page this is handled in the m->absent case above ! 1341: * (and if you change things here you should look above). ! 1342: */ ! 1343: #if TRACEFAULTPAGE ! 1344: dbgTrace(0xBEEF0014, (unsigned int) object, (unsigned int) m); /* (TEST/DEBUG) */ ! 1345: #endif ! 1346: if (object == first_object) ! 1347: first_m = m; ! 1348: else ! 1349: assert(m == VM_PAGE_NULL); ! 1350: ! 1351: XPR(XPR_VM_FAULT, ! 1352: "vm_f_page: no pager obj 0x%X, offset 0x%X, page 0x%X, next_obj 0x%X\n", ! 1353: (integer_t)object, offset, (integer_t)m, ! 1354: (integer_t)object->shadow, 0); ! 1355: /* ! 1356: * Move on to the next object. Lock the next ! 1357: * object before unlocking the current one. ! 1358: */ ! 1359: next_object = object->shadow; ! 1360: if (next_object == VM_OBJECT_NULL) { ! 1361: assert(!must_be_resident); ! 1362: ! 1363: /* ! 1364: * If there's no object left, fill the page ! 1365: * in the top object with zeros. But first we ! 1366: * need to allocate a real page. ! 1367: */ ! 1368: ! 1369: if (object != first_object) { ! 1370: vm_object_paging_end(object); ! 1371: vm_object_unlock(object); ! 1372: ! 1373: object = first_object; ! 1374: offset = first_offset; ! 1375: vm_object_lock(object); ! 1376: } ! 1377: ! 1378: m = first_m; ! 1379: assert(m->object == object); ! 1380: first_m = VM_PAGE_NULL; ! 1381: ! 1382: ! 1383: if ((vm_page_free_target - ! 1384: ((vm_page_free_target-vm_page_free_min)>>2)) ! 1385: > vm_page_free_count) { ! 1386: VM_PAGE_FREE(m); ! 1387: /* take an extra ref so object won't die */ ! 1388: assert(object->ref_count > 0); ! 1389: vm_fault_cleanup(object, first_m); ! 1390: vm_page_wait(); /* kick off pageout daemon */ ! 1391: if ((m = vm_page_grab()) != VM_PAGE_NULL) { ! 1392: /* need to kick off other parties */ ! 1393: /* waiting on free pages */ ! 1394: VM_PAGE_FREE(m); ! 1395: } ! 1396: return VM_FAULT_RETRY; ! 1397: } ! 1398: ! 1399: if (m->fictitious && !vm_page_convert(m)) { ! 1400: VM_PAGE_FREE(m); ! 1401: vm_fault_cleanup(object, VM_PAGE_NULL); ! 1402: return(VM_FAULT_MEMORY_SHORTAGE); ! 1403: } ! 1404: ! 1405: if (!no_zero_fill) { ! 1406: vm_object_unlock(object); ! 1407: vm_page_zero_fill(m); ! 1408: if (type_of_fault) ! 1409: *type_of_fault = DBG_ZERO_FILL_FAULT; ! 1410: VM_STAT(zero_fill_count++); ! 1411: vm_object_lock(object); ! 1412: } ! 1413: vm_page_lock_queues(); ! 1414: VM_PAGE_QUEUES_REMOVE(m); ! 1415: queue_enter(&vm_page_queue_inactive, ! 1416: m, vm_page_t, pageq); ! 1417: m->inactive = TRUE; ! 1418: vm_page_inactive_count++; ! 1419: vm_page_unlock_queues(); ! 1420: pmap_clear_modify(m->phys_addr); ! 1421: break; ! 1422: } ! 1423: else { ! 1424: if ((object != first_object) || must_be_resident) ! 1425: vm_object_paging_end(object); ! 1426: offset += object->shadow_offset; ! 1427: hi_offset += object->shadow_offset; ! 1428: lo_offset += object->shadow_offset; ! 1429: access_required = VM_PROT_READ; ! 1430: vm_object_lock(next_object); ! 1431: vm_object_unlock(object); ! 1432: object = next_object; ! 1433: vm_object_paging_begin(object); ! 1434: } ! 1435: } ! 1436: ! 1437: /* ! 1438: * PAGE HAS BEEN FOUND. ! 1439: * ! 1440: * This page (m) is: ! 1441: * busy, so that we can play with it; ! 1442: * not absent, so that nobody else will fill it; ! 1443: * possibly eligible for pageout; ! 1444: * ! 1445: * The top-level page (first_m) is: ! 1446: * VM_PAGE_NULL if the page was found in the ! 1447: * top-level object; ! 1448: * busy, not absent, and ineligible for pageout. ! 1449: * ! 1450: * The current object (object) is locked. A paging ! 1451: * reference is held for the current and top-level ! 1452: * objects. ! 1453: */ ! 1454: ! 1455: #if TRACEFAULTPAGE ! 1456: dbgTrace(0xBEEF0015, (unsigned int) object, (unsigned int) m); /* (TEST/DEBUG) */ ! 1457: #endif ! 1458: #if EXTRA_ASSERTIONS ! 1459: assert(m->busy && !m->absent); ! 1460: assert((first_m == VM_PAGE_NULL) || ! 1461: (first_m->busy && !first_m->absent && ! 1462: !first_m->active && !first_m->inactive)); ! 1463: #endif /* EXTRA_ASSERTIONS */ ! 1464: ! 1465: XPR(XPR_VM_FAULT, ! 1466: "vm_f_page: FOUND obj 0x%X, off 0x%X, page 0x%X, 1_obj 0x%X, 1_m 0x%X\n", ! 1467: (integer_t)object, offset, (integer_t)m, ! 1468: (integer_t)first_object, (integer_t)first_m); ! 1469: /* ! 1470: * If the page is being written, but isn't ! 1471: * already owned by the top-level object, ! 1472: * we have to copy it into a new page owned ! 1473: * by the top-level object. ! 1474: */ ! 1475: ! 1476: if (object != first_object) { ! 1477: /* ! 1478: * We only really need to copy if we ! 1479: * want to write it. ! 1480: */ ! 1481: ! 1482: #if TRACEFAULTPAGE ! 1483: dbgTrace(0xBEEF0016, (unsigned int) object, (unsigned int) fault_type); /* (TEST/DEBUG) */ ! 1484: #endif ! 1485: if (fault_type & VM_PROT_WRITE) { ! 1486: vm_page_t copy_m; ! 1487: ! 1488: assert(!must_be_resident); ! 1489: ! 1490: /* ! 1491: * If we try to collapse first_object at this ! 1492: * point, we may deadlock when we try to get ! 1493: * the lock on an intermediate object (since we ! 1494: * have the bottom object locked). We can't ! 1495: * unlock the bottom object, because the page ! 1496: * we found may move (by collapse) if we do. ! 1497: * ! 1498: * Instead, we first copy the page. Then, when ! 1499: * we have no more use for the bottom object, ! 1500: * we unlock it and try to collapse. ! 1501: * ! 1502: * Note that we copy the page even if we didn't ! 1503: * need to... that's the breaks. ! 1504: */ ! 1505: ! 1506: /* ! 1507: * Allocate a page for the copy ! 1508: */ ! 1509: copy_m = vm_page_grab(); ! 1510: if (copy_m == VM_PAGE_NULL) { ! 1511: RELEASE_PAGE(m); ! 1512: vm_fault_cleanup(object, first_m); ! 1513: return(VM_FAULT_MEMORY_SHORTAGE); ! 1514: } ! 1515: ! 1516: vm_object_unlock(object); ! 1517: ! 1518: XPR(XPR_VM_FAULT, ! 1519: "vm_f_page: page_copy obj 0x%X, offset 0x%X, m 0x%X, copy_m 0x%X\n", ! 1520: (integer_t)object, offset, ! 1521: (integer_t)m, (integer_t)copy_m, 0); ! 1522: vm_page_copy(m, copy_m); ! 1523: vm_object_lock(object); ! 1524: ! 1525: /* ! 1526: * If another map is truly sharing this ! 1527: * page with us, we have to flush all ! 1528: * uses of the original page, since we ! 1529: * can't distinguish those which want the ! 1530: * original from those which need the ! 1531: * new copy. ! 1532: * ! 1533: * XXXO If we know that only one map has ! 1534: * access to this page, then we could ! 1535: * avoid the pmap_page_protect() call. ! 1536: */ ! 1537: ! 1538: vm_page_lock_queues(); ! 1539: assert(!m->cleaning); ! 1540: pmap_page_protect(m->phys_addr, VM_PROT_NONE); ! 1541: vm_page_deactivate(m); ! 1542: copy_m->dirty = TRUE; ! 1543: /* ! 1544: * Setting reference here prevents this fault from ! 1545: * being counted as a (per-thread) reactivate as well ! 1546: * as a copy-on-write. ! 1547: */ ! 1548: first_m->reference = TRUE; ! 1549: vm_page_unlock_queues(); ! 1550: ! 1551: /* ! 1552: * We no longer need the old page or object. ! 1553: */ ! 1554: ! 1555: PAGE_WAKEUP_DONE(m); ! 1556: vm_object_paging_end(object); ! 1557: vm_object_unlock(object); ! 1558: ! 1559: if (type_of_fault) ! 1560: *type_of_fault = DBG_COW_FAULT; ! 1561: VM_STAT(cow_faults++); ! 1562: current_task()->cow_faults++; ! 1563: object = first_object; ! 1564: offset = first_offset; ! 1565: ! 1566: vm_object_lock(object); ! 1567: VM_PAGE_FREE(first_m); ! 1568: first_m = VM_PAGE_NULL; ! 1569: assert(copy_m->busy); ! 1570: vm_page_insert(copy_m, object, offset); ! 1571: m = copy_m; ! 1572: ! 1573: /* ! 1574: * Now that we've gotten the copy out of the ! 1575: * way, let's try to collapse the top object. ! 1576: * But we have to play ugly games with ! 1577: * paging_in_progress to do that... ! 1578: */ ! 1579: ! 1580: vm_object_paging_end(object); ! 1581: vm_object_collapse(object); ! 1582: vm_object_paging_begin(object); ! 1583: } ! 1584: else { ! 1585: *protection &= (~VM_PROT_WRITE); ! 1586: } ! 1587: } ! 1588: ! 1589: /* ! 1590: * Now check whether the page needs to be pushed into the ! 1591: * copy object. The use of asymmetric copy on write for ! 1592: * shared temporary objects means that we may do two copies to ! 1593: * satisfy the fault; one above to get the page from a ! 1594: * shadowed object, and one here to push it into the copy. ! 1595: */ ! 1596: ! 1597: while (first_object->copy_strategy == MEMORY_OBJECT_COPY_DELAY && ! 1598: (copy_object = first_object->copy) != VM_OBJECT_NULL) { ! 1599: vm_offset_t copy_offset; ! 1600: vm_page_t copy_m; ! 1601: ! 1602: #if TRACEFAULTPAGE ! 1603: dbgTrace(0xBEEF0017, (unsigned int) copy_object, (unsigned int) fault_type); /* (TEST/DEBUG) */ ! 1604: #endif ! 1605: /* ! 1606: * If the page is being written, but hasn't been ! 1607: * copied to the copy-object, we have to copy it there. ! 1608: */ ! 1609: ! 1610: if ((fault_type & VM_PROT_WRITE) == 0) { ! 1611: *protection &= ~VM_PROT_WRITE; ! 1612: break; ! 1613: } ! 1614: ! 1615: /* ! 1616: * If the page was guaranteed to be resident, ! 1617: * we must have already performed the copy. ! 1618: */ ! 1619: ! 1620: if (must_be_resident) ! 1621: break; ! 1622: ! 1623: /* ! 1624: * Try to get the lock on the copy_object. ! 1625: */ ! 1626: if (!vm_object_lock_try(copy_object)) { ! 1627: vm_object_unlock(object); ! 1628: ! 1629: mutex_pause(); /* wait a bit */ ! 1630: ! 1631: vm_object_lock(object); ! 1632: continue; ! 1633: } ! 1634: ! 1635: /* ! 1636: * Make another reference to the copy-object, ! 1637: * to keep it from disappearing during the ! 1638: * copy. ! 1639: */ ! 1640: assert(copy_object->ref_count > 0); ! 1641: copy_object->ref_count++; ! 1642: VM_OBJ_RES_INCR(copy_object); ! 1643: ! 1644: /* ! 1645: * Does the page exist in the copy? ! 1646: */ ! 1647: copy_offset = first_offset - copy_object->shadow_offset; ! 1648: if (copy_object->size <= copy_offset) ! 1649: /* ! 1650: * Copy object doesn't cover this page -- do nothing. ! 1651: */ ! 1652: ; ! 1653: else if ((copy_m = ! 1654: vm_page_lookup(copy_object, copy_offset)) != VM_PAGE_NULL) { ! 1655: /* Page currently exists in the copy object */ ! 1656: if (copy_m->busy) { ! 1657: /* ! 1658: * If the page is being brought ! 1659: * in, wait for it and then retry. ! 1660: */ ! 1661: RELEASE_PAGE(m); ! 1662: /* take an extra ref so object won't die */ ! 1663: assert(copy_object->ref_count > 0); ! 1664: copy_object->ref_count++; ! 1665: vm_object_res_reference(copy_object); ! 1666: vm_object_unlock(copy_object); ! 1667: vm_fault_cleanup(object, first_m); ! 1668: counter(c_vm_fault_page_block_backoff_kernel++); ! 1669: vm_object_lock(copy_object); ! 1670: assert(copy_object->ref_count > 0); ! 1671: VM_OBJ_RES_DECR(copy_object); ! 1672: copy_object->ref_count--; ! 1673: assert(copy_object->ref_count > 0); ! 1674: copy_m = vm_page_lookup(copy_object, copy_offset); ! 1675: if (copy_m != VM_PAGE_NULL && ! 1676: copy_m->busy) { ! 1677: PAGE_ASSERT_WAIT(copy_m, interruptible); ! 1678: vm_object_unlock(copy_object); ! 1679: thread_block((void (*)(void))0); ! 1680: vm_object_deallocate(copy_object); ! 1681: goto backoff; ! 1682: } else { ! 1683: vm_object_unlock(copy_object); ! 1684: vm_object_deallocate(copy_object); ! 1685: return VM_FAULT_RETRY; ! 1686: } ! 1687: } ! 1688: } ! 1689: else if (!PAGED_OUT(copy_object, copy_offset)) { ! 1690: /* ! 1691: * If PAGED_OUT is TRUE, then the page used to exist ! 1692: * in the copy-object, and has already been paged out. ! 1693: * We don't need to repeat this. If PAGED_OUT is ! 1694: * FALSE, then either we don't know (!pager_created, ! 1695: * for example) or it hasn't been paged out. ! 1696: * (VM_EXTERNAL_STATE_UNKNOWN||VM_EXTERNAL_STATE_ABSENT) ! 1697: * We must copy the page to the copy object. ! 1698: */ ! 1699: ! 1700: /* ! 1701: * Allocate a page for the copy ! 1702: */ ! 1703: copy_m = vm_page_alloc(copy_object, copy_offset); ! 1704: if (copy_m == VM_PAGE_NULL) { ! 1705: RELEASE_PAGE(m); ! 1706: VM_OBJ_RES_DECR(copy_object); ! 1707: copy_object->ref_count--; ! 1708: assert(copy_object->ref_count > 0); ! 1709: vm_object_unlock(copy_object); ! 1710: vm_fault_cleanup(object, first_m); ! 1711: return(VM_FAULT_MEMORY_SHORTAGE); ! 1712: } ! 1713: ! 1714: /* ! 1715: * Must copy page into copy-object. ! 1716: */ ! 1717: ! 1718: vm_page_copy(m, copy_m); ! 1719: ! 1720: /* ! 1721: * If the old page was in use by any users ! 1722: * of the copy-object, it must be removed ! 1723: * from all pmaps. (We can't know which ! 1724: * pmaps use it.) ! 1725: */ ! 1726: ! 1727: vm_page_lock_queues(); ! 1728: assert(!m->cleaning); ! 1729: pmap_page_protect(m->phys_addr, VM_PROT_NONE); ! 1730: copy_m->dirty = TRUE; ! 1731: vm_page_unlock_queues(); ! 1732: ! 1733: /* ! 1734: * If there's a pager, then immediately ! 1735: * page out this page, using the "initialize" ! 1736: * option. Else, we use the copy. ! 1737: */ ! 1738: ! 1739: if ! 1740: #if MACH_PAGEMAP ! 1741: ((!copy_object->pager_created) || ! 1742: vm_external_state_get( ! 1743: copy_object->existence_map, copy_offset) ! 1744: == VM_EXTERNAL_STATE_ABSENT) ! 1745: #else ! 1746: (!copy_object->pager_created) ! 1747: #endif ! 1748: { ! 1749: vm_page_lock_queues(); ! 1750: vm_page_activate(copy_m); ! 1751: vm_page_unlock_queues(); ! 1752: PAGE_WAKEUP_DONE(copy_m); ! 1753: } ! 1754: else { ! 1755: assert(copy_m->busy == TRUE); ! 1756: ! 1757: /* ! 1758: * The page is already ready for pageout: ! 1759: * not on pageout queues and busy. ! 1760: * Unlock everything except the ! 1761: * copy_object itself. ! 1762: */ ! 1763: ! 1764: vm_object_unlock(object); ! 1765: ! 1766: /* ! 1767: * Write the page to the copy-object, ! 1768: * flushing it from the kernel. ! 1769: */ ! 1770: ! 1771: vm_pageout_initialize_page(copy_m); ! 1772: ! 1773: /* ! 1774: * Since the pageout may have ! 1775: * temporarily dropped the ! 1776: * copy_object's lock, we ! 1777: * check whether we'll have ! 1778: * to deallocate the hard way. ! 1779: */ ! 1780: ! 1781: if ((copy_object->shadow != object) || ! 1782: (copy_object->ref_count == 1)) { ! 1783: vm_object_unlock(copy_object); ! 1784: vm_object_deallocate(copy_object); ! 1785: vm_object_lock(object); ! 1786: continue; ! 1787: } ! 1788: ! 1789: /* ! 1790: * Pick back up the old object's ! 1791: * lock. [It is safe to do so, ! 1792: * since it must be deeper in the ! 1793: * object tree.] ! 1794: */ ! 1795: ! 1796: vm_object_lock(object); ! 1797: } ! 1798: ! 1799: /* ! 1800: * Because we're pushing a page upward ! 1801: * in the object tree, we must restart ! 1802: * any faults that are waiting here. ! 1803: * [Note that this is an expansion of ! 1804: * PAGE_WAKEUP that uses the THREAD_RESTART ! 1805: * wait result]. Can't turn off the page's ! 1806: * busy bit because we're not done with it. ! 1807: */ ! 1808: ! 1809: if (m->wanted) { ! 1810: m->wanted = FALSE; ! 1811: thread_wakeup_with_result((event_t) m, ! 1812: THREAD_RESTART); ! 1813: } ! 1814: } ! 1815: ! 1816: /* ! 1817: * The reference count on copy_object must be ! 1818: * at least 2: one for our extra reference, ! 1819: * and at least one from the outside world ! 1820: * (we checked that when we last locked ! 1821: * copy_object). ! 1822: */ ! 1823: copy_object->ref_count--; ! 1824: assert(copy_object->ref_count > 0); ! 1825: VM_OBJ_RES_DECR(copy_object); ! 1826: vm_object_unlock(copy_object); ! 1827: ! 1828: break; ! 1829: } ! 1830: ! 1831: *result_page = m; ! 1832: *top_page = first_m; ! 1833: ! 1834: XPR(XPR_VM_FAULT, ! 1835: "vm_f_page: DONE obj 0x%X, offset 0x%X, m 0x%X, first_m 0x%X\n", ! 1836: (integer_t)object, offset, (integer_t)m, (integer_t)first_m, 0); ! 1837: /* ! 1838: * If the page can be written, assume that it will be. ! 1839: * [Earlier, we restrict the permission to allow write ! 1840: * access only if the fault so required, so we don't ! 1841: * mark read-only data as dirty.] ! 1842: */ ! 1843: ! 1844: #if !VM_FAULT_STATIC_CONFIG ! 1845: if (vm_fault_dirty_handling && (*protection & VM_PROT_WRITE)) ! 1846: m->dirty = TRUE; ! 1847: #endif ! 1848: #if TRACEFAULTPAGE ! 1849: dbgTrace(0xBEEF0018, (unsigned int) object, (unsigned int) vm_page_deactivate_behind); /* (TEST/DEBUG) */ ! 1850: #endif ! 1851: if (vm_page_deactivate_behind) { ! 1852: if (offset && /* don't underflow */ ! 1853: (object->last_alloc == (offset - PAGE_SIZE))) { ! 1854: m = vm_page_lookup(object, object->last_alloc); ! 1855: if ((m != VM_PAGE_NULL) && !m->busy) { ! 1856: vm_page_lock_queues(); ! 1857: vm_page_deactivate(m); ! 1858: vm_page_unlock_queues(); ! 1859: } ! 1860: #if TRACEFAULTPAGE ! 1861: dbgTrace(0xBEEF0019, (unsigned int) object, (unsigned int) m); /* (TEST/DEBUG) */ ! 1862: #endif ! 1863: } ! 1864: object->last_alloc = offset; ! 1865: } ! 1866: #if TRACEFAULTPAGE ! 1867: dbgTrace(0xBEEF001A, (unsigned int) VM_FAULT_SUCCESS, 0); /* (TEST/DEBUG) */ ! 1868: #endif ! 1869: return(VM_FAULT_SUCCESS); ! 1870: ! 1871: #if 0 ! 1872: block_and_backoff: ! 1873: vm_fault_cleanup(object, first_m); ! 1874: ! 1875: counter(c_vm_fault_page_block_backoff_kernel++); ! 1876: thread_block((void (*)(void))0); ! 1877: #endif ! 1878: ! 1879: backoff: ! 1880: if (thread->wait_result == THREAD_AWAKENED) ! 1881: { ! 1882: return VM_FAULT_RETRY; ! 1883: } ! 1884: else ! 1885: { ! 1886: return VM_FAULT_INTERRUPTED; ! 1887: } ! 1888: ! 1889: #undef RELEASE_PAGE ! 1890: } ! 1891: ! 1892: /* ! 1893: * Routine: vm_fault ! 1894: * Purpose: ! 1895: * Handle page faults, including pseudo-faults ! 1896: * used to change the wiring status of pages. ! 1897: * Returns: ! 1898: * Explicit continuations have been removed. ! 1899: * Implementation: ! 1900: * vm_fault and vm_fault_page save mucho state ! 1901: * in the moral equivalent of a closure. The state ! 1902: * structure is allocated when first entering vm_fault ! 1903: * and deallocated when leaving vm_fault. ! 1904: */ ! 1905: ! 1906: kern_return_t ! 1907: vm_fault( ! 1908: vm_map_t map, ! 1909: vm_offset_t vaddr, ! 1910: vm_prot_t fault_type, ! 1911: boolean_t change_wiring) ! 1912: { ! 1913: vm_map_version_t version; /* Map version for verificiation */ ! 1914: boolean_t wired; /* Should mapping be wired down? */ ! 1915: vm_object_t object; /* Top-level object */ ! 1916: vm_offset_t offset; /* Top-level offset */ ! 1917: vm_prot_t prot; /* Protection for mapping */ ! 1918: vm_behavior_t behavior; /* Expected paging behavior */ ! 1919: vm_offset_t lo_offset, hi_offset; ! 1920: vm_object_t old_copy_object; /* Saved copy object */ ! 1921: vm_page_t result_page; /* Result of vm_fault_page */ ! 1922: vm_page_t top_page; /* Placeholder page */ ! 1923: kern_return_t kr; ! 1924: ! 1925: register ! 1926: vm_page_t m; /* Fast access to result_page */ ! 1927: kern_return_t error_code; /* page error reasons */ ! 1928: register ! 1929: vm_object_t cur_object; ! 1930: register ! 1931: vm_offset_t cur_offset; ! 1932: vm_page_t cur_m; ! 1933: vm_object_t new_object; ! 1934: int type_of_fault; ! 1935: ! 1936: ! 1937: KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, 0)) | DBG_FUNC_START, ! 1938: vaddr, ! 1939: 0, ! 1940: 0, ! 1941: 0, ! 1942: 0); ! 1943: /* ! 1944: * assume we will hit a page in the cache ! 1945: * otherwise, explicitly override with ! 1946: * the real fault type once we determine it ! 1947: */ ! 1948: type_of_fault = DBG_CACHE_HIT_FAULT; ! 1949: ! 1950: VM_STAT(faults++); ! 1951: current_task()->faults++; ! 1952: ! 1953: RetryFault: ; ! 1954: ! 1955: /* ! 1956: * Find the backing store object and offset into ! 1957: * it to begin the search. ! 1958: */ ! 1959: vm_map_lock_read(map); ! 1960: kr = vm_map_lookup_locked(&map, vaddr, fault_type, &version, ! 1961: &object, &offset, ! 1962: &prot, &wired, ! 1963: &behavior, &lo_offset, &hi_offset); ! 1964: ! 1965: if (kr != KERN_SUCCESS) { ! 1966: vm_map_unlock_read(map); ! 1967: goto done; ! 1968: } ! 1969: ! 1970: /* ! 1971: * If the page is wired, we must fault for the current protection ! 1972: * value, to avoid further faults. ! 1973: */ ! 1974: ! 1975: if (wired) ! 1976: fault_type = prot | VM_PROT_WRITE; ! 1977: ! 1978: #if VM_FAULT_CLASSIFY ! 1979: /* ! 1980: * Temporary data gathering code ! 1981: */ ! 1982: vm_fault_classify(object, offset, fault_type); ! 1983: #endif ! 1984: /* ! 1985: * Fast fault code. The basic idea is to do as much as ! 1986: * possible while holding the map lock and object locks. ! 1987: * Busy pages are not used until the object lock has to ! 1988: * be dropped to do something (copy, zero fill, pmap enter). ! 1989: * Similarly, paging references aren't acquired until that ! 1990: * point, and object references aren't used. ! 1991: * ! 1992: * If we can figure out what to do ! 1993: * (zero fill, copy on write, pmap enter) while holding ! 1994: * the locks, then it gets done. Otherwise, we give up, ! 1995: * and use the original fault path (which doesn't hold ! 1996: * the map lock, and relies on busy pages). ! 1997: * The give up cases include: ! 1998: * - Have to talk to pager. ! 1999: * - Page is busy, absent or in error. ! 2000: * - Pager has locked out desired access. ! 2001: * - Fault needs to be restarted. ! 2002: * - Have to push page into copy object. ! 2003: * ! 2004: * The code is an infinite loop that moves one level down ! 2005: * the shadow chain each time. cur_object and cur_offset ! 2006: * refer to the current object being examined. object and offset ! 2007: * are the original object from the map. The loop is at the ! 2008: * top level if and only if object and cur_object are the same. ! 2009: * ! 2010: * Invariants: Map lock is held throughout. Lock is held on ! 2011: * original object and cur_object (if different) when ! 2012: * continuing or exiting loop. ! 2013: * ! 2014: */ ! 2015: ! 2016: ! 2017: /* ! 2018: * If this page is to be inserted in a copy delay object ! 2019: * for writing, and if the object has a copy, then the ! 2020: * copy delay strategy is implemented in the slow fault page. ! 2021: */ ! 2022: if (object->copy_strategy != MEMORY_OBJECT_COPY_DELAY || ! 2023: object->copy == VM_OBJECT_NULL || ! 2024: (fault_type & VM_PROT_WRITE) == 0) { ! 2025: cur_object = object; ! 2026: cur_offset = offset; ! 2027: ! 2028: while (TRUE) { ! 2029: m = vm_page_lookup(cur_object, cur_offset); ! 2030: if (m != VM_PAGE_NULL) { ! 2031: if (m->busy) ! 2032: break; ! 2033: ! 2034: if (m->unusual && (m->error || m->restart || ! 2035: m->absent || (fault_type & m->page_lock))) { ! 2036: ! 2037: /* ! 2038: * Unusual case. Give up. ! 2039: */ ! 2040: break; ! 2041: } ! 2042: ! 2043: /* ! 2044: * Two cases of map in faults: ! 2045: * - At top level w/o copy object. ! 2046: * - Read fault anywhere. ! 2047: * --> must disallow write. ! 2048: */ ! 2049: ! 2050: if (object == cur_object && ! 2051: object->copy == VM_OBJECT_NULL) ! 2052: goto FastMapInFault; ! 2053: ! 2054: if ((fault_type & VM_PROT_WRITE) == 0) { ! 2055: ! 2056: prot &= ~VM_PROT_WRITE; ! 2057: ! 2058: /* ! 2059: * Set up to map the page ... ! 2060: * mark the page busy, drop ! 2061: * locks and take a paging reference ! 2062: * on the object with the page. ! 2063: */ ! 2064: ! 2065: if (object != cur_object) { ! 2066: vm_object_unlock(object); ! 2067: object = cur_object; ! 2068: } ! 2069: FastMapInFault: ! 2070: m->busy = TRUE; ! 2071: ! 2072: vm_object_paging_begin(object); ! 2073: vm_object_unlock(object); ! 2074: ! 2075: FastPmapEnter: ! 2076: /* ! 2077: * Check a couple of global reasons to ! 2078: * be conservative about write access. ! 2079: * Then do the pmap_enter. ! 2080: */ ! 2081: #if !VM_FAULT_STATIC_CONFIG ! 2082: if (vm_fault_dirty_handling ! 2083: #if MACH_KDB ! 2084: || db_watchpoint_list ! 2085: #endif ! 2086: && (fault_type & VM_PROT_WRITE) == 0) ! 2087: prot &= ~VM_PROT_WRITE; ! 2088: #else /* STATIC_CONFIG */ ! 2089: #if MACH_KDB ! 2090: if (db_watchpoint_list ! 2091: && (fault_type & VM_PROT_WRITE) == 0) ! 2092: prot &= ~VM_PROT_WRITE; ! 2093: #endif /* MACH_KDB */ ! 2094: #endif /* STATIC_CONFIG */ ! 2095: PMAP_ENTER(vm_map_pmap(map), vaddr, m, ! 2096: prot, wired); ! 2097: ! 2098: if (m->clustered) { ! 2099: vm_pagein_cluster_used++; ! 2100: m->clustered = FALSE; ! 2101: ! 2102: pmap_attribute(vm_map_pmap(map), ! 2103: vaddr, ! 2104: PAGE_SIZE, ! 2105: MATTR_CACHE, ! 2106: &mv_cache_sync); ! 2107: } ! 2108: /* ! 2109: * Grab the object lock to manipulate ! 2110: * the page queues. Change wiring ! 2111: * case is obvious. In soft ref bits ! 2112: * case activate page only if it fell ! 2113: * off paging queues, otherwise just ! 2114: * activate it if it's inactive. ! 2115: * ! 2116: * NOTE: original vm_fault code will ! 2117: * move active page to back of active ! 2118: * queue. This code doesn't. ! 2119: */ ! 2120: vm_object_lock(object); ! 2121: vm_page_lock_queues(); ! 2122: ! 2123: m->reference = TRUE; ! 2124: ! 2125: if (change_wiring) { ! 2126: if (wired) ! 2127: vm_page_wire(m); ! 2128: else ! 2129: vm_page_unwire(m); ! 2130: } ! 2131: #if VM_FAULT_STATIC_CONFIG ! 2132: else { ! 2133: if (!m->active && !m->inactive) ! 2134: vm_page_activate(m); ! 2135: } ! 2136: #else ! 2137: else if (software_reference_bits) { ! 2138: if (!m->active && !m->inactive) ! 2139: vm_page_activate(m); ! 2140: } ! 2141: else if (!m->active) { ! 2142: vm_page_activate(m); ! 2143: } ! 2144: #endif ! 2145: vm_page_unlock_queues(); ! 2146: ! 2147: /* ! 2148: * That's it, clean up and return. ! 2149: */ ! 2150: PAGE_WAKEUP_DONE(m); ! 2151: vm_object_paging_end(object); ! 2152: vm_object_unlock(object); ! 2153: vm_map_unlock_read(map); ! 2154: ! 2155: KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, 0)) | DBG_FUNC_END, ! 2156: vaddr, ! 2157: type_of_fault, ! 2158: KERN_SUCCESS, ! 2159: 0, ! 2160: 0); ! 2161: return KERN_SUCCESS; ! 2162: } ! 2163: ! 2164: /* ! 2165: * Copy on write fault. If objects match, then ! 2166: * object->copy must not be NULL (else control ! 2167: * would be in previous code block), and we ! 2168: * have a potential push into the copy object ! 2169: * with which we won't cope here. ! 2170: */ ! 2171: ! 2172: if (cur_object == object) ! 2173: break; ! 2174: ! 2175: /* ! 2176: * This is now a shadow based copy on write ! 2177: * fault -- it requires a copy up the shadow ! 2178: * chain. ! 2179: * ! 2180: * Allocate a page in the original top level ! 2181: * object. Give up if allocate fails. Also ! 2182: * need to remember current page, as it's the ! 2183: * source of the copy. ! 2184: */ ! 2185: cur_m = m; ! 2186: m = vm_page_alloc(object, offset); ! 2187: if (m == VM_PAGE_NULL) { ! 2188: break; ! 2189: } ! 2190: ! 2191: /* ! 2192: * Now do the copy. Mark the source busy ! 2193: * and take out paging references on both ! 2194: * objects. ! 2195: * ! 2196: * NOTE: This code holds the map lock across ! 2197: * the page copy. ! 2198: */ ! 2199: ! 2200: cur_m->busy = TRUE; ! 2201: ! 2202: vm_object_paging_begin(cur_object); ! 2203: vm_object_unlock(cur_object); ! 2204: vm_object_paging_begin(object); ! 2205: vm_object_unlock(object); ! 2206: ! 2207: vm_page_copy(cur_m, m); ! 2208: type_of_fault = DBG_COW_FAULT; ! 2209: VM_STAT(cow_faults++); ! 2210: current_task()->cow_faults++; ! 2211: ! 2212: /* ! 2213: * Now cope with the source page and object ! 2214: * If the top object has a ref count of 1 ! 2215: * then no other map can access it, and hence ! 2216: * it's not necessary to do the pmap_page_protect. ! 2217: */ ! 2218: ! 2219: vm_object_lock(object); ! 2220: vm_object_lock(cur_object); ! 2221: ! 2222: vm_page_lock_queues(); ! 2223: vm_page_deactivate(cur_m); ! 2224: m->dirty = TRUE; ! 2225: if (object->ref_count != 1) ! 2226: pmap_page_protect(cur_m->phys_addr, ! 2227: VM_PROT_NONE); ! 2228: vm_page_unlock_queues(); ! 2229: ! 2230: PAGE_WAKEUP_DONE(cur_m); ! 2231: vm_object_paging_end(cur_object); ! 2232: vm_object_unlock(cur_object); ! 2233: ! 2234: /* ! 2235: * Slight hack to call vm_object collapse ! 2236: * and then reuse common map in code. ! 2237: * note that the object lock was taken above. ! 2238: */ ! 2239: ! 2240: vm_object_paging_end(object); ! 2241: vm_object_collapse(object); ! 2242: vm_object_paging_begin(object); ! 2243: vm_object_unlock(object); ! 2244: ! 2245: goto FastPmapEnter; ! 2246: } ! 2247: else { ! 2248: ! 2249: /* ! 2250: * No page at cur_object, cur_offset ! 2251: */ ! 2252: ! 2253: if (cur_object->pager_created) { ! 2254: ! 2255: /* ! 2256: * Have to talk to the pager. Give up. ! 2257: */ ! 2258: ! 2259: break; ! 2260: } ! 2261: ! 2262: ! 2263: if (cur_object->shadow == VM_OBJECT_NULL) { ! 2264: ! 2265: /* ! 2266: * Zero fill fault. Page gets ! 2267: * filled in top object. Insert ! 2268: * page, then drop any lower lock. ! 2269: * Give up if no page. ! 2270: */ ! 2271: if ((vm_page_free_target - ! 2272: ((vm_page_free_target-vm_page_free_min)>>2)) ! 2273: > vm_page_free_count) { ! 2274: break; ! 2275: } ! 2276: m = vm_page_alloc(object, offset); ! 2277: if (m == VM_PAGE_NULL) { ! 2278: break; ! 2279: } ! 2280: ! 2281: if (cur_object != object) ! 2282: vm_object_unlock(cur_object); ! 2283: ! 2284: vm_object_paging_begin(object); ! 2285: vm_object_unlock(object); ! 2286: ! 2287: /* ! 2288: * Now zero fill page and map it. ! 2289: * the page is probably going to ! 2290: * be written soon, so don't bother ! 2291: * to clear the modified bit ! 2292: * ! 2293: * NOTE: This code holds the map ! 2294: * lock across the zero fill. ! 2295: */ ! 2296: ! 2297: if (!map->no_zero_fill) { ! 2298: vm_page_zero_fill(m); ! 2299: type_of_fault = DBG_ZERO_FILL_FAULT; ! 2300: VM_STAT(zero_fill_count++); ! 2301: } ! 2302: vm_page_lock_queues(); ! 2303: VM_PAGE_QUEUES_REMOVE(m); ! 2304: queue_enter(&vm_page_queue_inactive, ! 2305: m, vm_page_t, pageq); ! 2306: m->inactive = TRUE; ! 2307: vm_page_inactive_count++; ! 2308: vm_page_unlock_queues(); ! 2309: goto FastPmapEnter; ! 2310: } ! 2311: ! 2312: /* ! 2313: * On to the next level ! 2314: */ ! 2315: ! 2316: cur_offset += cur_object->shadow_offset; ! 2317: new_object = cur_object->shadow; ! 2318: vm_object_lock(new_object); ! 2319: if (cur_object != object) ! 2320: vm_object_unlock(cur_object); ! 2321: cur_object = new_object; ! 2322: ! 2323: continue; ! 2324: } ! 2325: } ! 2326: ! 2327: /* ! 2328: * Cleanup from fast fault failure. Drop any object ! 2329: * lock other than original and drop map lock. ! 2330: */ ! 2331: ! 2332: if (object != cur_object) ! 2333: vm_object_unlock(cur_object); ! 2334: } ! 2335: vm_map_unlock_read(map); ! 2336: ! 2337: /* ! 2338: * Make a reference to this object to ! 2339: * prevent its disposal while we are messing with ! 2340: * it. Once we have the reference, the map is free ! 2341: * to be diddled. Since objects reference their ! 2342: * shadows (and copies), they will stay around as well. ! 2343: */ ! 2344: ! 2345: assert(object->ref_count > 0); ! 2346: object->ref_count++; ! 2347: vm_object_res_reference(object); ! 2348: vm_object_paging_begin(object); ! 2349: ! 2350: XPR(XPR_VM_FAULT,"vm_fault -> vm_fault_page\n",0,0,0,0,0); ! 2351: kr = vm_fault_page(object, offset, fault_type, ! 2352: (change_wiring && !wired), ! 2353: ((!change_wiring) ? THREAD_ABORTSAFE : THREAD_UNINT), ! 2354: lo_offset, hi_offset, behavior, ! 2355: &prot, &result_page, &top_page, ! 2356: &type_of_fault, ! 2357: &error_code, map->no_zero_fill, FALSE); ! 2358: ! 2359: /* ! 2360: * If we didn't succeed, lose the object reference immediately. ! 2361: */ ! 2362: ! 2363: if (kr != VM_FAULT_SUCCESS) ! 2364: vm_object_deallocate(object); ! 2365: ! 2366: /* ! 2367: * See why we failed, and take corrective action. ! 2368: */ ! 2369: ! 2370: switch (kr) { ! 2371: case VM_FAULT_SUCCESS: ! 2372: break; ! 2373: case VM_FAULT_RETRY: ! 2374: goto RetryFault; ! 2375: case VM_FAULT_INTERRUPTED: ! 2376: kr = KERN_SUCCESS; ! 2377: goto done; ! 2378: case VM_FAULT_MEMORY_SHORTAGE: ! 2379: VM_PAGE_WAIT(); ! 2380: goto RetryFault; ! 2381: case VM_FAULT_FICTITIOUS_SHORTAGE: ! 2382: vm_page_more_fictitious(); ! 2383: goto RetryFault; ! 2384: case VM_FAULT_MEMORY_ERROR: ! 2385: if (error_code) ! 2386: kr = error_code; ! 2387: else ! 2388: kr = KERN_MEMORY_ERROR; ! 2389: goto done; ! 2390: } ! 2391: ! 2392: m = result_page; ! 2393: ! 2394: assert((change_wiring && !wired) ? ! 2395: (top_page == VM_PAGE_NULL) : ! 2396: ((top_page == VM_PAGE_NULL) == (m->object == object))); ! 2397: ! 2398: /* ! 2399: * How to clean up the result of vm_fault_page. This ! 2400: * happens whether the mapping is entered or not. ! 2401: */ ! 2402: ! 2403: #define UNLOCK_AND_DEALLOCATE \ ! 2404: MACRO_BEGIN \ ! 2405: vm_fault_cleanup(m->object, top_page); \ ! 2406: vm_object_deallocate(object); \ ! 2407: MACRO_END ! 2408: ! 2409: /* ! 2410: * What to do with the resulting page from vm_fault_page ! 2411: * if it doesn't get entered into the physical map: ! 2412: */ ! 2413: ! 2414: #define RELEASE_PAGE(m) \ ! 2415: MACRO_BEGIN \ ! 2416: PAGE_WAKEUP_DONE(m); \ ! 2417: vm_page_lock_queues(); \ ! 2418: if (!m->active && !m->inactive) \ ! 2419: vm_page_activate(m); \ ! 2420: vm_page_unlock_queues(); \ ! 2421: MACRO_END ! 2422: ! 2423: /* ! 2424: * We must verify that the maps have not changed ! 2425: * since our last lookup. ! 2426: */ ! 2427: ! 2428: old_copy_object = m->object->copy; ! 2429: ! 2430: vm_object_unlock(m->object); ! 2431: while (!vm_map_verify(map, &version)) { ! 2432: vm_object_t retry_object; ! 2433: vm_offset_t retry_offset; ! 2434: vm_prot_t retry_prot; ! 2435: ! 2436: /* ! 2437: * To avoid trying to write_lock the map while another ! 2438: * thread has it read_locked (in vm_map_pageable), we ! 2439: * do not try for write permission. If the page is ! 2440: * still writable, we will get write permission. If it ! 2441: * is not, or has been marked needs_copy, we enter the ! 2442: * mapping without write permission, and will merely ! 2443: * take another fault. ! 2444: */ ! 2445: vm_map_lock_read(map); ! 2446: kr = vm_map_lookup_locked(&map, vaddr, ! 2447: fault_type & ~VM_PROT_WRITE, &version, ! 2448: &retry_object, &retry_offset, &retry_prot, ! 2449: &wired, &behavior, &lo_offset, &hi_offset); ! 2450: vm_map_unlock_read(map); ! 2451: ! 2452: if (kr != KERN_SUCCESS) { ! 2453: vm_object_lock(m->object); ! 2454: RELEASE_PAGE(m); ! 2455: UNLOCK_AND_DEALLOCATE; ! 2456: goto done; ! 2457: } ! 2458: ! 2459: vm_object_unlock(retry_object); ! 2460: vm_object_lock(m->object); ! 2461: ! 2462: if ((retry_object != object) || ! 2463: (retry_offset != offset)) { ! 2464: RELEASE_PAGE(m); ! 2465: UNLOCK_AND_DEALLOCATE; ! 2466: goto RetryFault; ! 2467: } ! 2468: ! 2469: /* ! 2470: * Check whether the protection has changed or the object ! 2471: * has been copied while we left the map unlocked. ! 2472: */ ! 2473: prot &= retry_prot; ! 2474: vm_object_unlock(m->object); ! 2475: } ! 2476: vm_object_lock(m->object); ! 2477: ! 2478: /* ! 2479: * If the copy object changed while the top-level object ! 2480: * was unlocked, then we must take away write permission. ! 2481: */ ! 2482: ! 2483: if (m->object->copy != old_copy_object) ! 2484: prot &= ~VM_PROT_WRITE; ! 2485: ! 2486: /* ! 2487: * If we want to wire down this page, but no longer have ! 2488: * adequate permissions, we must start all over. ! 2489: */ ! 2490: ! 2491: if (wired && (fault_type != (prot|VM_PROT_WRITE))) { ! 2492: vm_map_verify_done(map, &version); ! 2493: RELEASE_PAGE(m); ! 2494: UNLOCK_AND_DEALLOCATE; ! 2495: goto RetryFault; ! 2496: } ! 2497: ! 2498: /* ! 2499: * It's critically important that a wired-down page be faulted ! 2500: * only once in each map for which it is wired. ! 2501: */ ! 2502: vm_object_unlock(m->object); ! 2503: ! 2504: /* ! 2505: * Put this page into the physical map. ! 2506: * We had to do the unlock above because pmap_enter ! 2507: * may cause other faults. The page may be on ! 2508: * the pageout queues. If the pageout daemon comes ! 2509: * across the page, it will remove it from the queues. ! 2510: */ ! 2511: PMAP_ENTER(map->pmap, vaddr, m, prot, wired); ! 2512: ! 2513: /* Sync I & D caches for new mapping*/ ! 2514: pmap_attribute(map->pmap, ! 2515: vaddr, ! 2516: PAGE_SIZE, ! 2517: MATTR_CACHE, ! 2518: &mv_cache_sync); ! 2519: ! 2520: /* ! 2521: * If the page is not wired down and isn't already ! 2522: * on a pageout queue, then put it where the ! 2523: * pageout daemon can find it. ! 2524: */ ! 2525: vm_object_lock(m->object); ! 2526: vm_page_lock_queues(); ! 2527: if (change_wiring) { ! 2528: if (wired) ! 2529: vm_page_wire(m); ! 2530: else ! 2531: vm_page_unwire(m); ! 2532: } ! 2533: #if VM_FAULT_STATIC_CONFIG ! 2534: else { ! 2535: if (!m->active && !m->inactive) ! 2536: vm_page_activate(m); ! 2537: m->reference = TRUE; ! 2538: } ! 2539: #else ! 2540: else if (software_reference_bits) { ! 2541: if (!m->active && !m->inactive) ! 2542: vm_page_activate(m); ! 2543: m->reference = TRUE; ! 2544: } else { ! 2545: vm_page_activate(m); ! 2546: } ! 2547: #endif ! 2548: vm_page_unlock_queues(); ! 2549: ! 2550: /* ! 2551: * Unlock everything, and return ! 2552: */ ! 2553: ! 2554: vm_map_verify_done(map, &version); ! 2555: PAGE_WAKEUP_DONE(m); ! 2556: kr = KERN_SUCCESS; ! 2557: UNLOCK_AND_DEALLOCATE; ! 2558: ! 2559: #undef UNLOCK_AND_DEALLOCATE ! 2560: #undef RELEASE_PAGE ! 2561: ! 2562: done: ! 2563: KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, 0)) | DBG_FUNC_END, ! 2564: vaddr, ! 2565: type_of_fault, ! 2566: kr, ! 2567: 0, ! 2568: 0); ! 2569: return(kr); ! 2570: } ! 2571: ! 2572: /* ! 2573: * vm_fault_wire: ! 2574: * ! 2575: * Wire down a range of virtual addresses in a map. ! 2576: */ ! 2577: kern_return_t ! 2578: vm_fault_wire( ! 2579: vm_map_t map, ! 2580: vm_map_entry_t entry) ! 2581: { ! 2582: ! 2583: register vm_offset_t va; ! 2584: register pmap_t pmap; ! 2585: register vm_offset_t end_addr = entry->vme_end; ! 2586: register kern_return_t rc; ! 2587: ! 2588: assert(entry->in_transition); ! 2589: pmap = vm_map_pmap(map); ! 2590: ! 2591: /* ! 2592: * Inform the physical mapping system that the ! 2593: * range of addresses may not fault, so that ! 2594: * page tables and such can be locked down as well. ! 2595: */ ! 2596: ! 2597: pmap_pageable(pmap, entry->vme_start, end_addr, FALSE); ! 2598: ! 2599: /* ! 2600: * We simulate a fault to get the page and enter it ! 2601: * in the physical map. ! 2602: */ ! 2603: ! 2604: for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) { ! 2605: if ((rc = vm_fault_wire_fast(map, va, entry)) != KERN_SUCCESS) { ! 2606: rc = vm_fault(map, va, VM_PROT_NONE, TRUE); ! 2607: } ! 2608: ! 2609: if (rc != KERN_SUCCESS) { ! 2610: struct vm_map_entry tmp_entry = *entry; ! 2611: ! 2612: /* unwire wired pages */ ! 2613: tmp_entry.vme_end = va; ! 2614: vm_fault_unwire(map, &tmp_entry, FALSE); ! 2615: ! 2616: return rc; ! 2617: } ! 2618: } ! 2619: return KERN_SUCCESS; ! 2620: } ! 2621: ! 2622: /* ! 2623: * vm_fault_unwire: ! 2624: * ! 2625: * Unwire a range of virtual addresses in a map. ! 2626: */ ! 2627: void ! 2628: vm_fault_unwire( ! 2629: vm_map_t map, ! 2630: vm_map_entry_t entry, ! 2631: boolean_t deallocate) ! 2632: { ! 2633: register vm_offset_t va; ! 2634: register pmap_t pmap; ! 2635: register vm_offset_t end_addr = entry->vme_end; ! 2636: vm_object_t object; ! 2637: ! 2638: pmap = vm_map_pmap(map); ! 2639: ! 2640: object = (entry->is_sub_map) ! 2641: ? VM_OBJECT_NULL : entry->object.vm_object; ! 2642: ! 2643: /* ! 2644: * Since the pages are wired down, we must be able to ! 2645: * get their mappings from the physical map system. ! 2646: */ ! 2647: ! 2648: for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) { ! 2649: pmap_change_wiring(pmap, va, FALSE); ! 2650: ! 2651: if (object == VM_OBJECT_NULL) { ! 2652: (void) vm_fault(map, va, VM_PROT_NONE, TRUE); ! 2653: } else { ! 2654: vm_prot_t prot; ! 2655: vm_page_t result_page; ! 2656: vm_page_t top_page; ! 2657: vm_object_t result_object; ! 2658: vm_fault_return_t result; ! 2659: ! 2660: do { ! 2661: prot = VM_PROT_NONE; ! 2662: ! 2663: vm_object_lock(object); ! 2664: vm_object_paging_begin(object); ! 2665: XPR(XPR_VM_FAULT, ! 2666: "vm_fault_unwire -> vm_fault_page\n", ! 2667: 0,0,0,0,0); ! 2668: result = vm_fault_page(object, ! 2669: entry->offset + ! 2670: (va - entry->vme_start), ! 2671: VM_PROT_NONE, TRUE, ! 2672: THREAD_UNINT, ! 2673: entry->offset, ! 2674: entry->offset + ! 2675: (entry->vme_end ! 2676: - entry->vme_start), ! 2677: entry->behavior, ! 2678: &prot, ! 2679: &result_page, ! 2680: &top_page, ! 2681: (int *)0, ! 2682: 0, map->no_zero_fill, ! 2683: FALSE); ! 2684: } while (result == VM_FAULT_RETRY); ! 2685: ! 2686: if (result != VM_FAULT_SUCCESS) ! 2687: panic("vm_fault_unwire: failure"); ! 2688: ! 2689: result_object = result_page->object; ! 2690: if (deallocate) { ! 2691: assert(!result_page->fictitious); ! 2692: pmap_page_protect(result_page->phys_addr, ! 2693: VM_PROT_NONE); ! 2694: VM_PAGE_FREE(result_page); ! 2695: } else { ! 2696: vm_page_lock_queues(); ! 2697: vm_page_unwire(result_page); ! 2698: vm_page_unlock_queues(); ! 2699: PAGE_WAKEUP_DONE(result_page); ! 2700: } ! 2701: ! 2702: vm_fault_cleanup(result_object, top_page); ! 2703: } ! 2704: } ! 2705: ! 2706: /* ! 2707: * Inform the physical mapping system that the range ! 2708: * of addresses may fault, so that page tables and ! 2709: * such may be unwired themselves. ! 2710: */ ! 2711: ! 2712: pmap_pageable(pmap, entry->vme_start, end_addr, TRUE); ! 2713: ! 2714: } ! 2715: ! 2716: /* ! 2717: * vm_fault_wire_fast: ! 2718: * ! 2719: * Handle common case of a wire down page fault at the given address. ! 2720: * If successful, the page is inserted into the associated physical map. ! 2721: * The map entry is passed in to avoid the overhead of a map lookup. ! 2722: * ! 2723: * NOTE: the given address should be truncated to the ! 2724: * proper page address. ! 2725: * ! 2726: * KERN_SUCCESS is returned if the page fault is handled; otherwise, ! 2727: * a standard error specifying why the fault is fatal is returned. ! 2728: * ! 2729: * The map in question must be referenced, and remains so. ! 2730: * Caller has a read lock on the map. ! 2731: * ! 2732: * This is a stripped version of vm_fault() for wiring pages. Anything ! 2733: * other than the common case will return KERN_FAILURE, and the caller ! 2734: * is expected to call vm_fault(). ! 2735: */ ! 2736: kern_return_t ! 2737: vm_fault_wire_fast( ! 2738: vm_map_t map, ! 2739: vm_offset_t va, ! 2740: vm_map_entry_t entry) ! 2741: { ! 2742: vm_object_t object; ! 2743: vm_offset_t offset; ! 2744: register vm_page_t m; ! 2745: vm_prot_t prot; ! 2746: thread_act_t thr_act; ! 2747: ! 2748: VM_STAT(faults++); ! 2749: ! 2750: if((thr_act=current_act()) && (thr_act->task != TASK_NULL)) ! 2751: thr_act->task->faults++; ! 2752: ! 2753: /* ! 2754: * Recovery actions ! 2755: */ ! 2756: ! 2757: #undef RELEASE_PAGE ! 2758: #define RELEASE_PAGE(m) { \ ! 2759: PAGE_WAKEUP_DONE(m); \ ! 2760: vm_page_lock_queues(); \ ! 2761: vm_page_unwire(m); \ ! 2762: vm_page_unlock_queues(); \ ! 2763: } ! 2764: ! 2765: ! 2766: #undef UNLOCK_THINGS ! 2767: #define UNLOCK_THINGS { \ ! 2768: object->paging_in_progress--; \ ! 2769: vm_object_unlock(object); \ ! 2770: } ! 2771: ! 2772: #undef UNLOCK_AND_DEALLOCATE ! 2773: #define UNLOCK_AND_DEALLOCATE { \ ! 2774: UNLOCK_THINGS; \ ! 2775: vm_object_deallocate(object); \ ! 2776: } ! 2777: /* ! 2778: * Give up and have caller do things the hard way. ! 2779: */ ! 2780: ! 2781: #define GIVE_UP { \ ! 2782: UNLOCK_AND_DEALLOCATE; \ ! 2783: return(KERN_FAILURE); \ ! 2784: } ! 2785: ! 2786: ! 2787: /* ! 2788: * If this entry is not directly to a vm_object, bail out. ! 2789: */ ! 2790: if (entry->is_sub_map) ! 2791: return(KERN_FAILURE); ! 2792: ! 2793: /* ! 2794: * Find the backing store object and offset into it. ! 2795: */ ! 2796: ! 2797: object = entry->object.vm_object; ! 2798: offset = (va - entry->vme_start) + entry->offset; ! 2799: prot = entry->protection; ! 2800: ! 2801: /* ! 2802: * Make a reference to this object to prevent its ! 2803: * disposal while we are messing with it. ! 2804: */ ! 2805: ! 2806: vm_object_lock(object); ! 2807: assert(object->ref_count > 0); ! 2808: object->ref_count++; ! 2809: vm_object_res_reference(object); ! 2810: object->paging_in_progress++; ! 2811: ! 2812: /* ! 2813: * INVARIANTS (through entire routine): ! 2814: * ! 2815: * 1) At all times, we must either have the object ! 2816: * lock or a busy page in some object to prevent ! 2817: * some other thread from trying to bring in ! 2818: * the same page. ! 2819: * ! 2820: * 2) Once we have a busy page, we must remove it from ! 2821: * the pageout queues, so that the pageout daemon ! 2822: * will not grab it away. ! 2823: * ! 2824: */ ! 2825: ! 2826: /* ! 2827: * Look for page in top-level object. If it's not there or ! 2828: * there's something going on, give up. ! 2829: */ ! 2830: m = vm_page_lookup(object, offset); ! 2831: if ((m == VM_PAGE_NULL) || (m->busy) || ! 2832: (m->unusual && ( m->error || m->restart || m->absent || ! 2833: prot & m->page_lock))) { ! 2834: ! 2835: GIVE_UP; ! 2836: } ! 2837: ! 2838: /* ! 2839: * Wire the page down now. All bail outs beyond this ! 2840: * point must unwire the page. ! 2841: */ ! 2842: ! 2843: vm_page_lock_queues(); ! 2844: vm_page_wire(m); ! 2845: vm_page_unlock_queues(); ! 2846: ! 2847: /* ! 2848: * Mark page busy for other threads. ! 2849: */ ! 2850: assert(!m->busy); ! 2851: m->busy = TRUE; ! 2852: assert(!m->absent); ! 2853: ! 2854: /* ! 2855: * Give up if the page is being written and there's a copy object ! 2856: */ ! 2857: if ((object->copy != VM_OBJECT_NULL) && (prot & VM_PROT_WRITE)) { ! 2858: RELEASE_PAGE(m); ! 2859: GIVE_UP; ! 2860: } ! 2861: ! 2862: /* ! 2863: * Put this page into the physical map. ! 2864: * We have to unlock the object because pmap_enter ! 2865: * may cause other faults. ! 2866: */ ! 2867: vm_object_unlock(object); ! 2868: ! 2869: PMAP_ENTER(map->pmap, va, m, prot, TRUE); ! 2870: /* Sync I & D caches for new mapping */ ! 2871: pmap_attribute(map->pmap, ! 2872: va, ! 2873: PAGE_SIZE, ! 2874: MATTR_CACHE, ! 2875: &mv_cache_sync); ! 2876: ! 2877: /* ! 2878: * Must relock object so that paging_in_progress can be cleared. ! 2879: */ ! 2880: vm_object_lock(object); ! 2881: ! 2882: /* ! 2883: * Unlock everything, and return ! 2884: */ ! 2885: ! 2886: PAGE_WAKEUP_DONE(m); ! 2887: UNLOCK_AND_DEALLOCATE; ! 2888: ! 2889: return(KERN_SUCCESS); ! 2890: ! 2891: } ! 2892: ! 2893: /* ! 2894: * Routine: vm_fault_copy_cleanup ! 2895: * Purpose: ! 2896: * Release a page used by vm_fault_copy. ! 2897: */ ! 2898: ! 2899: void ! 2900: vm_fault_copy_cleanup( ! 2901: vm_page_t page, ! 2902: vm_page_t top_page) ! 2903: { ! 2904: vm_object_t object = page->object; ! 2905: ! 2906: vm_object_lock(object); ! 2907: PAGE_WAKEUP_DONE(page); ! 2908: vm_page_lock_queues(); ! 2909: if (!page->active && !page->inactive) ! 2910: vm_page_activate(page); ! 2911: vm_page_unlock_queues(); ! 2912: vm_fault_cleanup(object, top_page); ! 2913: } ! 2914: ! 2915: void ! 2916: vm_fault_copy_dst_cleanup( ! 2917: vm_page_t page) ! 2918: { ! 2919: vm_object_t object; ! 2920: ! 2921: if (page != VM_PAGE_NULL) { ! 2922: object = page->object; ! 2923: vm_object_lock(object); ! 2924: vm_page_lock_queues(); ! 2925: vm_page_unwire(page); ! 2926: vm_page_unlock_queues(); ! 2927: vm_object_paging_end(object); ! 2928: vm_object_unlock(object); ! 2929: } ! 2930: } ! 2931: ! 2932: /* ! 2933: * Routine: vm_fault_copy ! 2934: * ! 2935: * Purpose: ! 2936: * Copy pages from one virtual memory object to another -- ! 2937: * neither the source nor destination pages need be resident. ! 2938: * ! 2939: * Before actually copying a page, the version associated with ! 2940: * the destination address map wil be verified. ! 2941: * ! 2942: * In/out conditions: ! 2943: * The caller must hold a reference, but not a lock, to ! 2944: * each of the source and destination objects and to the ! 2945: * destination map. ! 2946: * ! 2947: * Results: ! 2948: * Returns KERN_SUCCESS if no errors were encountered in ! 2949: * reading or writing the data. Returns KERN_INTERRUPTED if ! 2950: * the operation was interrupted (only possible if the ! 2951: * "interruptible" argument is asserted). Other return values ! 2952: * indicate a permanent error in copying the data. ! 2953: * ! 2954: * The actual amount of data copied will be returned in the ! 2955: * "copy_size" argument. In the event that the destination map ! 2956: * verification failed, this amount may be less than the amount ! 2957: * requested. ! 2958: */ ! 2959: kern_return_t ! 2960: vm_fault_copy( ! 2961: vm_object_t src_object, ! 2962: vm_offset_t src_offset, ! 2963: vm_size_t *src_size, /* INOUT */ ! 2964: vm_object_t dst_object, ! 2965: vm_offset_t dst_offset, ! 2966: vm_map_t dst_map, ! 2967: vm_map_version_t *dst_version, ! 2968: int interruptible) ! 2969: { ! 2970: vm_page_t result_page; ! 2971: ! 2972: vm_page_t src_page; ! 2973: vm_page_t src_top_page; ! 2974: vm_prot_t src_prot; ! 2975: ! 2976: vm_page_t dst_page; ! 2977: vm_page_t dst_top_page; ! 2978: vm_prot_t dst_prot; ! 2979: ! 2980: vm_size_t amount_left; ! 2981: vm_object_t old_copy_object; ! 2982: kern_return_t error = 0; ! 2983: ! 2984: vm_size_t part_size; ! 2985: ! 2986: /* ! 2987: * In order not to confuse the clustered pageins, align ! 2988: * the different offsets on a page boundary. ! 2989: */ ! 2990: vm_offset_t src_lo_offset = trunc_page(src_offset); ! 2991: vm_offset_t dst_lo_offset = trunc_page(dst_offset); ! 2992: vm_offset_t src_hi_offset = round_page(src_offset + *src_size); ! 2993: vm_offset_t dst_hi_offset = round_page(dst_offset + *src_size); ! 2994: ! 2995: #define RETURN(x) \ ! 2996: MACRO_BEGIN \ ! 2997: *src_size -= amount_left; \ ! 2998: MACRO_RETURN(x); \ ! 2999: MACRO_END ! 3000: ! 3001: amount_left = *src_size; ! 3002: do { /* while (amount_left > 0) */ ! 3003: /* ! 3004: * There may be a deadlock if both source and destination ! 3005: * pages are the same. To avoid this deadlock, the copy must ! 3006: * start by getting the destination page in order to apply ! 3007: * COW semantics if any. ! 3008: */ ! 3009: ! 3010: RetryDestinationFault: ; ! 3011: ! 3012: dst_prot = VM_PROT_WRITE|VM_PROT_READ; ! 3013: ! 3014: vm_object_lock(dst_object); ! 3015: vm_object_paging_begin(dst_object); ! 3016: ! 3017: XPR(XPR_VM_FAULT,"vm_fault_copy -> vm_fault_page\n",0,0,0,0,0); ! 3018: switch (vm_fault_page(dst_object, ! 3019: trunc_page(dst_offset), ! 3020: VM_PROT_WRITE|VM_PROT_READ, ! 3021: FALSE, ! 3022: THREAD_UNINT, ! 3023: dst_lo_offset, ! 3024: dst_hi_offset, ! 3025: VM_BEHAVIOR_SEQUENTIAL, ! 3026: &dst_prot, ! 3027: &dst_page, ! 3028: &dst_top_page, ! 3029: (int *)0, ! 3030: &error, ! 3031: dst_map->no_zero_fill, ! 3032: FALSE)) { ! 3033: case VM_FAULT_SUCCESS: ! 3034: break; ! 3035: case VM_FAULT_RETRY: ! 3036: goto RetryDestinationFault; ! 3037: case VM_FAULT_INTERRUPTED: ! 3038: RETURN(MACH_SEND_INTERRUPTED); ! 3039: case VM_FAULT_MEMORY_SHORTAGE: ! 3040: VM_PAGE_WAIT(); ! 3041: goto RetryDestinationFault; ! 3042: case VM_FAULT_FICTITIOUS_SHORTAGE: ! 3043: vm_page_more_fictitious(); ! 3044: goto RetryDestinationFault; ! 3045: case VM_FAULT_MEMORY_ERROR: ! 3046: if (error) ! 3047: return (error); ! 3048: else ! 3049: return(KERN_MEMORY_ERROR); ! 3050: } ! 3051: assert ((dst_prot & VM_PROT_WRITE) != VM_PROT_NONE); ! 3052: ! 3053: old_copy_object = dst_page->object->copy; ! 3054: ! 3055: /* ! 3056: * There exists the possiblity that the source and ! 3057: * destination page are the same. But we can't ! 3058: * easily determine that now. If they are the ! 3059: * same, the call to vm_fault_page() for the ! 3060: * destination page will deadlock. To prevent this we ! 3061: * wire the page so we can drop busy without having ! 3062: * the page daemon steal the page. We clean up the ! 3063: * top page but keep the paging reference on the object ! 3064: * holding the dest page so it doesn't go away. ! 3065: */ ! 3066: ! 3067: vm_page_lock_queues(); ! 3068: vm_page_wire(dst_page); ! 3069: vm_page_unlock_queues(); ! 3070: PAGE_WAKEUP_DONE(dst_page); ! 3071: vm_object_unlock(dst_page->object); ! 3072: ! 3073: if (dst_top_page != VM_PAGE_NULL) { ! 3074: vm_object_lock(dst_object); ! 3075: VM_PAGE_FREE(dst_top_page); ! 3076: vm_object_paging_end(dst_object); ! 3077: vm_object_unlock(dst_object); ! 3078: } ! 3079: ! 3080: RetrySourceFault: ; ! 3081: ! 3082: if (src_object == VM_OBJECT_NULL) { ! 3083: /* ! 3084: * No source object. We will just ! 3085: * zero-fill the page in dst_object. ! 3086: */ ! 3087: src_page = VM_PAGE_NULL; ! 3088: } else { ! 3089: vm_object_lock(src_object); ! 3090: src_page = vm_page_lookup(src_object, ! 3091: trunc_page(src_offset)); ! 3092: if (src_page == dst_page) ! 3093: src_prot = dst_prot; ! 3094: else { ! 3095: src_prot = VM_PROT_READ; ! 3096: vm_object_paging_begin(src_object); ! 3097: ! 3098: XPR(XPR_VM_FAULT, ! 3099: "vm_fault_copy(2) -> vm_fault_page\n", ! 3100: 0,0,0,0,0); ! 3101: switch (vm_fault_page(src_object, ! 3102: trunc_page(src_offset), ! 3103: VM_PROT_READ, ! 3104: FALSE, ! 3105: interruptible, ! 3106: src_lo_offset, ! 3107: src_hi_offset, ! 3108: VM_BEHAVIOR_SEQUENTIAL, ! 3109: &src_prot, ! 3110: &result_page, ! 3111: &src_top_page, ! 3112: (int *)0, ! 3113: &error, ! 3114: FALSE, ! 3115: FALSE)) { ! 3116: ! 3117: case VM_FAULT_SUCCESS: ! 3118: break; ! 3119: case VM_FAULT_RETRY: ! 3120: goto RetrySourceFault; ! 3121: case VM_FAULT_INTERRUPTED: ! 3122: vm_fault_copy_dst_cleanup(dst_page); ! 3123: RETURN(MACH_SEND_INTERRUPTED); ! 3124: case VM_FAULT_MEMORY_SHORTAGE: ! 3125: VM_PAGE_WAIT(); ! 3126: goto RetrySourceFault; ! 3127: case VM_FAULT_FICTITIOUS_SHORTAGE: ! 3128: vm_page_more_fictitious(); ! 3129: goto RetrySourceFault; ! 3130: case VM_FAULT_MEMORY_ERROR: ! 3131: vm_fault_copy_dst_cleanup(dst_page); ! 3132: if (error) ! 3133: return (error); ! 3134: else ! 3135: return(KERN_MEMORY_ERROR); ! 3136: } ! 3137: ! 3138: src_page = result_page; ! 3139: ! 3140: assert((src_top_page == VM_PAGE_NULL) == ! 3141: (src_page->object == src_object)); ! 3142: } ! 3143: assert ((src_prot & VM_PROT_READ) != VM_PROT_NONE); ! 3144: vm_object_unlock(src_page->object); ! 3145: } ! 3146: ! 3147: if (!vm_map_verify(dst_map, dst_version)) { ! 3148: if (src_page != VM_PAGE_NULL && src_page != dst_page) ! 3149: vm_fault_copy_cleanup(src_page, src_top_page); ! 3150: vm_fault_copy_dst_cleanup(dst_page); ! 3151: break; ! 3152: } ! 3153: ! 3154: vm_object_lock(dst_page->object); ! 3155: ! 3156: if (dst_page->object->copy != old_copy_object) { ! 3157: vm_object_unlock(dst_page->object); ! 3158: vm_map_verify_done(dst_map, dst_version); ! 3159: if (src_page != VM_PAGE_NULL && src_page != dst_page) ! 3160: vm_fault_copy_cleanup(src_page, src_top_page); ! 3161: vm_fault_copy_dst_cleanup(dst_page); ! 3162: break; ! 3163: } ! 3164: vm_object_unlock(dst_page->object); ! 3165: ! 3166: /* ! 3167: * Copy the page, and note that it is dirty ! 3168: * immediately. ! 3169: */ ! 3170: ! 3171: if (!page_aligned(src_offset) || ! 3172: !page_aligned(dst_offset) || ! 3173: !page_aligned(amount_left)) { ! 3174: ! 3175: vm_offset_t src_po, ! 3176: dst_po; ! 3177: ! 3178: src_po = src_offset - trunc_page(src_offset); ! 3179: dst_po = dst_offset - trunc_page(dst_offset); ! 3180: ! 3181: if (dst_po > src_po) { ! 3182: part_size = PAGE_SIZE - dst_po; ! 3183: } else { ! 3184: part_size = PAGE_SIZE - src_po; ! 3185: } ! 3186: if (part_size > (amount_left)){ ! 3187: part_size = amount_left; ! 3188: } ! 3189: ! 3190: if (src_page == VM_PAGE_NULL) { ! 3191: vm_page_part_zero_fill(dst_page, ! 3192: dst_po, part_size); ! 3193: } else { ! 3194: vm_page_part_copy(src_page, src_po, ! 3195: dst_page, dst_po, part_size); ! 3196: if(!dst_page->dirty){ ! 3197: vm_object_lock(dst_object); ! 3198: dst_page->dirty = TRUE; ! 3199: vm_object_unlock(dst_page->object); ! 3200: } ! 3201: ! 3202: } ! 3203: } else { ! 3204: part_size = PAGE_SIZE; ! 3205: ! 3206: if (src_page == VM_PAGE_NULL) ! 3207: vm_page_zero_fill(dst_page); ! 3208: else{ ! 3209: vm_page_copy(src_page, dst_page); ! 3210: if(!dst_page->dirty){ ! 3211: vm_object_lock(dst_object); ! 3212: dst_page->dirty = TRUE; ! 3213: vm_object_unlock(dst_page->object); ! 3214: } ! 3215: } ! 3216: ! 3217: } ! 3218: ! 3219: /* ! 3220: * Unlock everything, and return ! 3221: */ ! 3222: ! 3223: vm_map_verify_done(dst_map, dst_version); ! 3224: ! 3225: if (src_page != VM_PAGE_NULL && src_page != dst_page) ! 3226: vm_fault_copy_cleanup(src_page, src_top_page); ! 3227: vm_fault_copy_dst_cleanup(dst_page); ! 3228: ! 3229: amount_left -= part_size; ! 3230: src_offset += part_size; ! 3231: dst_offset += part_size; ! 3232: } while (amount_left > 0); ! 3233: ! 3234: RETURN(KERN_SUCCESS); ! 3235: #undef RETURN ! 3236: ! 3237: /*NOTREACHED*/ ! 3238: } ! 3239: ! 3240: #ifdef notdef ! 3241: ! 3242: /* ! 3243: * Routine: vm_fault_page_overwrite ! 3244: * ! 3245: * Description: ! 3246: * A form of vm_fault_page that assumes that the ! 3247: * resulting page will be overwritten in its entirety, ! 3248: * making it unnecessary to obtain the correct *contents* ! 3249: * of the page. ! 3250: * ! 3251: * Implementation: ! 3252: * XXX Untested. Also unused. Eventually, this technology ! 3253: * could be used in vm_fault_copy() to advantage. ! 3254: */ ! 3255: vm_fault_return_t ! 3256: vm_fault_page_overwrite( ! 3257: register ! 3258: vm_object_t dst_object, ! 3259: vm_offset_t dst_offset, ! 3260: vm_page_t *result_page) /* OUT */ ! 3261: { ! 3262: register ! 3263: vm_page_t dst_page; ! 3264: thread_t thread = current_thread(); ! 3265: ! 3266: #define interruptible THREAD_UNINT /* XXX */ ! 3267: ! 3268: while (TRUE) { ! 3269: /* ! 3270: * Look for a page at this offset ! 3271: */ ! 3272: ! 3273: while ((dst_page = vm_page_lookup(dst_object, dst_offset)) ! 3274: == VM_PAGE_NULL) { ! 3275: /* ! 3276: * No page, no problem... just allocate one. ! 3277: */ ! 3278: ! 3279: dst_page = vm_page_alloc(dst_object, dst_offset); ! 3280: if (dst_page == VM_PAGE_NULL) { ! 3281: vm_object_unlock(dst_object); ! 3282: VM_PAGE_WAIT(); ! 3283: vm_object_lock(dst_object); ! 3284: continue; ! 3285: } ! 3286: ! 3287: /* ! 3288: * Pretend that the memory manager ! 3289: * write-protected the page. ! 3290: * ! 3291: * Note that we will be asking for write ! 3292: * permission without asking for the data ! 3293: * first. ! 3294: */ ! 3295: ! 3296: dst_page->overwriting = TRUE; ! 3297: dst_page->page_lock = VM_PROT_WRITE; ! 3298: dst_page->absent = TRUE; ! 3299: dst_page->unusual = TRUE; ! 3300: dst_object->absent_count++; ! 3301: ! 3302: break; ! 3303: ! 3304: /* ! 3305: * When we bail out, we might have to throw ! 3306: * away the page created here. ! 3307: */ ! 3308: ! 3309: #define DISCARD_PAGE \ ! 3310: MACRO_BEGIN \ ! 3311: vm_object_lock(dst_object); \ ! 3312: dst_page = vm_page_lookup(dst_object, dst_offset); \ ! 3313: if ((dst_page != VM_PAGE_NULL) && dst_page->overwriting) \ ! 3314: VM_PAGE_FREE(dst_page); \ ! 3315: vm_object_unlock(dst_object); \ ! 3316: MACRO_END ! 3317: } ! 3318: ! 3319: /* ! 3320: * If the page is write-protected... ! 3321: */ ! 3322: ! 3323: if (dst_page->page_lock & VM_PROT_WRITE) { ! 3324: /* ! 3325: * ... and an unlock request hasn't been sent ! 3326: */ ! 3327: ! 3328: if ( ! (dst_page->unlock_request & VM_PROT_WRITE)) { ! 3329: vm_prot_t u; ! 3330: kern_return_t rc; ! 3331: ! 3332: /* ! 3333: * ... then send one now. ! 3334: */ ! 3335: ! 3336: if (!dst_object->pager_ready) { ! 3337: vm_object_assert_wait(dst_object, ! 3338: VM_OBJECT_EVENT_PAGER_READY, ! 3339: interruptible); ! 3340: vm_object_unlock(dst_object); ! 3341: thread_block((void (*)(void))0); ! 3342: if (thread->wait_result != ! 3343: THREAD_AWAKENED) { ! 3344: DISCARD_PAGE; ! 3345: return(VM_FAULT_INTERRUPTED); ! 3346: } ! 3347: continue; ! 3348: } ! 3349: ! 3350: u = dst_page->unlock_request |= VM_PROT_WRITE; ! 3351: vm_object_unlock(dst_object); ! 3352: ! 3353: if ((rc = memory_object_data_unlock( ! 3354: dst_object->pager, ! 3355: dst_object->pager_request, ! 3356: dst_offset + dst_object->paging_offset, ! 3357: PAGE_SIZE, ! 3358: u)) != KERN_SUCCESS) { ! 3359: if (vm_fault_debug) ! 3360: printf("vm_object_overwrite: memory_object_data_unlock failed\n"); ! 3361: DISCARD_PAGE; ! 3362: return((rc == MACH_SEND_INTERRUPTED) ? ! 3363: VM_FAULT_INTERRUPTED : ! 3364: VM_FAULT_MEMORY_ERROR); ! 3365: } ! 3366: vm_object_lock(dst_object); ! 3367: continue; ! 3368: } ! 3369: ! 3370: /* ... fall through to wait below */ ! 3371: } else { ! 3372: /* ! 3373: * If the page isn't being used for other ! 3374: * purposes, then we're done. ! 3375: */ ! 3376: if ( ! (dst_page->busy || dst_page->absent || ! 3377: dst_page->error || dst_page->restart) ) ! 3378: break; ! 3379: } ! 3380: ! 3381: PAGE_ASSERT_WAIT(dst_page, interruptible); ! 3382: vm_object_unlock(dst_object); ! 3383: thread_block((void (*)(void))0); ! 3384: if (thread->wait_result != THREAD_AWAKENED) { ! 3385: DISCARD_PAGE; ! 3386: return(VM_FAULT_INTERRUPTED); ! 3387: } ! 3388: } ! 3389: ! 3390: *result_page = dst_page; ! 3391: return(VM_FAULT_SUCCESS); ! 3392: ! 3393: #undef interruptible ! 3394: #undef DISCARD_PAGE ! 3395: } ! 3396: ! 3397: #endif /* notdef */ ! 3398: ! 3399: #if VM_FAULT_CLASSIFY ! 3400: /* ! 3401: * Temporary statistics gathering support. ! 3402: */ ! 3403: ! 3404: /* ! 3405: * Statistics arrays: ! 3406: */ ! 3407: #define VM_FAULT_TYPES_MAX 5 ! 3408: #define VM_FAULT_LEVEL_MAX 8 ! 3409: ! 3410: int vm_fault_stats[VM_FAULT_TYPES_MAX][VM_FAULT_LEVEL_MAX]; ! 3411: ! 3412: #define VM_FAULT_TYPE_ZERO_FILL 0 ! 3413: #define VM_FAULT_TYPE_MAP_IN 1 ! 3414: #define VM_FAULT_TYPE_PAGER 2 ! 3415: #define VM_FAULT_TYPE_COPY 3 ! 3416: #define VM_FAULT_TYPE_OTHER 4 ! 3417: ! 3418: ! 3419: void ! 3420: vm_fault_classify(vm_object_t object, ! 3421: vm_offset_t offset, ! 3422: vm_prot_t fault_type) ! 3423: { ! 3424: int type, level = 0; ! 3425: vm_page_t m; ! 3426: ! 3427: while (TRUE) { ! 3428: m = vm_page_lookup(object, offset); ! 3429: if (m != VM_PAGE_NULL) { ! 3430: if (m->busy || m->error || m->restart || m->absent || ! 3431: fault_type & m->page_lock) { ! 3432: type = VM_FAULT_TYPE_OTHER; ! 3433: break; ! 3434: } ! 3435: if (((fault_type & VM_PROT_WRITE) == 0) || ! 3436: ((level == 0) && object->copy == VM_OBJECT_NULL)) { ! 3437: type = VM_FAULT_TYPE_MAP_IN; ! 3438: break; ! 3439: } ! 3440: type = VM_FAULT_TYPE_COPY; ! 3441: break; ! 3442: } ! 3443: else { ! 3444: if (object->pager_created) { ! 3445: type = VM_FAULT_TYPE_PAGER; ! 3446: break; ! 3447: } ! 3448: if (object->shadow == VM_OBJECT_NULL) { ! 3449: type = VM_FAULT_TYPE_ZERO_FILL; ! 3450: break; ! 3451: } ! 3452: ! 3453: offset += object->shadow_offset; ! 3454: object = object->shadow; ! 3455: level++; ! 3456: continue; ! 3457: } ! 3458: } ! 3459: ! 3460: if (level > VM_FAULT_LEVEL_MAX) ! 3461: level = VM_FAULT_LEVEL_MAX; ! 3462: ! 3463: vm_fault_stats[type][level] += 1; ! 3464: ! 3465: return; ! 3466: } ! 3467: ! 3468: /* cleanup routine to call from debugger */ ! 3469: ! 3470: void ! 3471: vm_fault_classify_init(void) ! 3472: { ! 3473: int type, level; ! 3474: ! 3475: for (type = 0; type < VM_FAULT_TYPES_MAX; type++) { ! 3476: for (level = 0; level < VM_FAULT_LEVEL_MAX; level++) { ! 3477: vm_fault_stats[type][level] = 0; ! 3478: } ! 3479: } ! 3480: ! 3481: return; ! 3482: } ! 3483: #endif /* VM_FAULT_CLASSIFY */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.