Annotation of kernel/vm/vm_fault.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* 
        !            26:  * Mach Operating System
        !            27:  * Copyright (c) 1987 Carnegie-Mellon University
        !            28:  * All rights reserved.  The CMU software License Agreement specifies
        !            29:  * the terms and conditions for use and redistribution.
        !            30:  */
        !            31: /*
        !            32:  *     File:   vm_fault.c
        !            33:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
        !            34:  *
        !            35:  *     Copyright (C) 1985, Avadis Tevanian, Jr., Michael Wayne Young
        !            36:  *
        !            37:  *     Page fault handling module.
        !            38:  */
        !            39: 
        !            40: #import <mach_xp.h>
        !            41: 
        !            42: #define        USE_VERSIONS    MACH_XP
        !            43: 
        !            44: #import <mach/kern_return.h>
        !            45: #import <mach/message.h>       /* for error codes */
        !            46: #import <kern/thread.h>
        !            47: #import <kern/sched_prim.h>
        !            48: #import <vm/vm_map.h>
        !            49: #import <vm/vm_object.h>
        !            50: #import <vm/vm_page.h>
        !            51: #import <vm/pmap.h>
        !            52: #import <mach/vm_statistics.h>
        !            53: #import <vm/vm_pageout.h>
        !            54: #import <mach/vm_param.h>
        !            55: 
        !            56: 
        !            57: /*
        !            58:  *     vm_fault:
        !            59:  *
        !            60:  *     Handle a page fault occuring at the given address,
        !            61:  *     requiring the given permissions, in the map specified.
        !            62:  *     If successful, the page is inserted into the
        !            63:  *     associated physical map.
        !            64:  *
        !            65:  *     NOTE: the given address should be truncated to the
        !            66:  *     proper page address.
        !            67:  *
        !            68:  *     KERN_SUCCESS is returned if the page fault is handled; otherwise,
        !            69:  *     a standard error specifying why the fault is fatal is returned.
        !            70:  *
        !            71:  *
        !            72:  *     The map in question must be referenced, and remains so.
        !            73:  *     Caller may hold no locks.
        !            74:  */
        !            75: #if    NeXT
        !            76: kern_return_t vm_fault(map, vaddr, fault_type, change_wiring, error)
        !            77:        vm_map_t        map;
        !            78:        vm_offset_t     vaddr;
        !            79:        vm_prot_t       fault_type;
        !            80:        boolean_t       change_wiring;
        !            81:        int             *error;
        !            82: #else  NeXT
        !            83: kern_return_t vm_fault(map, vaddr, fault_type, change_wiring)
        !            84:        vm_map_t        map;
        !            85:        vm_offset_t     vaddr;
        !            86:        vm_prot_t       fault_type;
        !            87:        boolean_t       change_wiring;
        !            88: #endif NeXT
        !            89: {
        !            90:        vm_object_t             first_object;
        !            91:        vm_offset_t             first_offset;
        !            92: #if    USE_VERSIONS
        !            93:        vm_map_version_t        version;
        !            94: #else  USE_VERSIONS
        !            95:        vm_map_entry_t          entry;
        !            96: #endif USE_VERSIONS
        !            97:        register vm_object_t    object;
        !            98:        register vm_offset_t    offset;
        !            99:        register vm_page_t      m;
        !           100:        vm_page_t               first_m;
        !           101:        vm_prot_t               prot;
        !           102:        kern_return_t           result;
        !           103:        boolean_t               wired;
        !           104:        boolean_t               su;
        !           105: #if    !USE_VERSIONS
        !           106:        boolean_t               lookup_still_valid;
        !           107: #endif !USE_VERSIONS
        !           108:        boolean_t               page_exists;
        !           109:        vm_page_t               old_m;
        !           110:        vm_object_t             next_object;
        !           111: 
        !           112:        vm_stat.faults++;               /* needs lock XXX */
        !           113: /*
        !           114:  *     Recovery actions
        !           115:  */
        !           116: #if    MACH_XP
        !           117: /* vm_page_free does a PAGE_WAKEUP anyway */
        !           118: #define        FREE_PAGE(m) {                                  \
        !           119:        vm_page_lock_queues();                          \
        !           120:        vm_page_free(m);                                \
        !           121:        vm_page_unlock_queues();                        \
        !           122: }
        !           123: #else  MACH_XP
        !           124: #define        FREE_PAGE(m)    {                               \
        !           125:        PAGE_WAKEUP(m);                                 \
        !           126:        vm_page_lock_queues();                          \
        !           127:        vm_page_free(m);                                \
        !           128:        vm_page_unlock_queues();                        \
        !           129: }
        !           130: #endif MACH_XP
        !           131: 
        !           132: #define        RELEASE_PAGE(m) {                               \
        !           133:        PAGE_WAKEUP(m);                                 \
        !           134:        vm_page_lock_queues();                          \
        !           135:        vm_page_activate(m);                            \
        !           136:        vm_page_unlock_queues();                        \
        !           137: }
        !           138: 
        !           139: #if    USE_VERSIONS
        !           140: #define        UNLOCK_MAP
        !           141: #else  USE_VERSIONS
        !           142: #define        UNLOCK_MAP      {                               \
        !           143:        if (lookup_still_valid) {                       \
        !           144:                vm_map_lookup_done(map, entry);         \
        !           145:                lookup_still_valid = FALSE;             \
        !           146:        }                                               \
        !           147: }
        !           148: #endif USE_VERSIONS
        !           149: 
        !           150: #define        UNLOCK_THINGS   {                               \
        !           151:        object->paging_in_progress--;                   \
        !           152:        vm_object_unlock(object);                       \
        !           153:        if (object != first_object) {                   \
        !           154:                vm_object_lock(first_object);           \
        !           155:                FREE_PAGE(first_m);                     \
        !           156:                first_object->paging_in_progress--;     \
        !           157:                vm_object_unlock(first_object);         \
        !           158:        }                                               \
        !           159:        UNLOCK_MAP;                                     \
        !           160: }
        !           161: 
        !           162: #define        UNLOCK_AND_DEALLOCATE   {                       \
        !           163:        UNLOCK_THINGS;                                  \
        !           164:        vm_object_deallocate(first_object);             \
        !           165: }
        !           166: 
        !           167:     RetryFault: ;
        !           168: 
        !           169:        /*
        !           170:         *      Find the backing store object and offset into
        !           171:         *      it to begin the search.
        !           172:         */
        !           173: 
        !           174: #if    USE_VERSIONS
        !           175:        if ((result = vm_map_lookup(&map, vaddr, fault_type, &version,
        !           176: #else  USE_VERSIONS
        !           177:        if ((result = vm_map_lookup(&map, vaddr, fault_type, &entry,
        !           178: #endif USE_VERSIONS
        !           179:                        &first_object, &first_offset,
        !           180:                        &prot, &wired, &su)) != KERN_SUCCESS) {
        !           181:                return(result);
        !           182:        }
        !           183: #if    !USE_VERSIONS
        !           184:        lookup_still_valid = TRUE;
        !           185: #endif !USE_VERSIONS
        !           186: 
        !           187:        if (wired)
        !           188:                fault_type = prot;
        !           189: 
        !           190:        first_m = VM_PAGE_NULL;
        !           191: 
        !           192:        /*
        !           193:         *      Make a reference to this object to
        !           194:         *      prevent its disposal while we are messing with
        !           195:         *      it.  Once we have the reference, the map is free
        !           196:         *      to be diddled.  Since objects reference their
        !           197:         *      shadows (and copies), they will stay around as well.
        !           198:         */
        !           199: 
        !           200: #if    !USE_VERSIONS
        !           201:        vm_object_lock(first_object);
        !           202: #endif !USE_VERSIONS
        !           203: 
        !           204:        first_object->ref_count++;
        !           205:        first_object->paging_in_progress++;
        !           206: 
        !           207:        /*
        !           208:         *      INVARIANTS (through entire routine):
        !           209:         *
        !           210:         *      1)      At all times, we must either have the object
        !           211:         *              lock or a busy page in some object to prevent
        !           212:         *              some other thread from trying to bring in
        !           213:         *              the same page.
        !           214:         *
        !           215:         *              Note that we cannot hold any locks during the
        !           216:         *              pager access or when waiting for memory, so
        !           217:         *              we use a busy page then.
        !           218:         *
        !           219:         *              Note also that we aren't as concerned about
        !           220:         *              more than one thead attempting to pager_data_unlock
        !           221:         *              the same page at once, so we don't hold the page
        !           222:         *              as busy then, but do record the highest unlock
        !           223:         *              value so far.  [Unlock requests may also be delivered
        !           224:         *              out of order.]
        !           225:         *
        !           226:         *      2)      Once we have a busy page, we must remove it from
        !           227:         *              the pageout queues, so that the pageout daemon
        !           228:         *              will not grab it away.
        !           229:         *
        !           230:         *      3)      To prevent another thread from racing us down the
        !           231:         *              shadow chain and entering a new page in the top
        !           232:         *              object before we do, we must keep a busy page in
        !           233:         *              the top object while following the shadow chain.
        !           234:         *
        !           235:         *      4)      We must increment paging_in_progress on any object
        !           236:         *              for which we have a busy page, to prevent
        !           237:         *              vm_object_collapse from removing the busy page
        !           238:         *              without our noticing.
        !           239:         */
        !           240: 
        !           241:        /*
        !           242:         *      Search for the page at object/offset.
        !           243:         */
        !           244: 
        !           245:        object = first_object;
        !           246:        offset = first_offset;
        !           247: 
        !           248:        /*
        !           249:         *      See whether this page is resident
        !           250:         */
        !           251: 
        !           252:        while (TRUE) {
        !           253:                m = vm_page_lookup(object, offset);
        !           254:                if (m != VM_PAGE_NULL) {
        !           255:                        /*
        !           256:                         *      If the page is in error, give up now.
        !           257:                         */
        !           258: 
        !           259:                        if (m->error) {
        !           260:                                FREE_PAGE(m);
        !           261:                                UNLOCK_AND_DEALLOCATE;
        !           262:                                return(KERN_MEMORY_ERROR);
        !           263:                        }
        !           264: 
        !           265:                        /*
        !           266:                         *      If the page is being brought in,
        !           267:                         *      wait for it and then retry.
        !           268:                         */
        !           269:                        if (m->busy) {
        !           270:                                kern_return_t   wait_result;
        !           271: #if SCRUBVM3
        !           272:                                /* hint if we miss it its ok */
        !           273:                                if (m->dry_vp){
        !           274:                                    vm_page_lock_queues();
        !           275:                                    (void) vm_page_completeio(m, TRUE);
        !           276:                                    vm_page_unlock_queues();
        !           277:                                } else {
        !           278: #endif
        !           279:                                    PAGE_ASSERT_WAIT(m, !change_wiring);
        !           280:                                    UNLOCK_MAP;                         
        !           281:                                    vm_object_unlock(object);
        !           282:                                    thread_block();
        !           283:                                    wait_result = current_thread()->wait_result;
        !           284:                                    vm_object_lock(object);
        !           285:                                    if (wait_result == THREAD_RESTART) {
        !           286:                                            UNLOCK_AND_DEALLOCATE;
        !           287:                                            goto RetryFault;
        !           288:                                    }
        !           289:                                    if (wait_result != THREAD_AWAKENED) {
        !           290:                                            UNLOCK_AND_DEALLOCATE;
        !           291:                                            return(KERN_SUCCESS);
        !           292:                                    }
        !           293:                                    continue;
        !           294: #if SCRUBVM3
        !           295:                                }
        !           296: #endif
        !           297:                        }
        !           298: 
        !           299:                        /*
        !           300:                         *      If the page isn't busy, but is absent,
        !           301:                         *      then it was deemed "unavailable".
        !           302:                         */
        !           303: 
        !           304:                        if (m->absent) {
        !           305:                                /*
        !           306:                                 * Remove the non-existent page (unless it's
        !           307:                                 * in the top object) and move on down to the
        !           308:                                 * next object (if there is one).
        !           309:                                 */
        !           310:                                offset += object->shadow_offset;
        !           311:                                next_object = object->shadow;
        !           312:                                if (next_object == VM_OBJECT_NULL) {
        !           313:                                        /*
        !           314:                                         * Absent page at bottom of shadow
        !           315:                                         * chain; zero fill the page we left
        !           316:                                         * busy in the first object, and flush
        !           317:                                         * the absent page.
        !           318:                                         */
        !           319:                                        if (object != first_object) {
        !           320:                                                m->busy = m->absent = FALSE;
        !           321:                                                FREE_PAGE(m);
        !           322:                                                object->paging_in_progress--;
        !           323:                                                vm_object_unlock(object);
        !           324:                                                object = first_object;
        !           325:                                                offset = first_offset;
        !           326:                                                m = first_m;
        !           327:                                                vm_object_lock(object);
        !           328:                                        }
        !           329:                                        first_m = VM_PAGE_NULL;
        !           330:                                        vm_page_zero_fill(m);
        !           331:                                        vm_stat.zero_fill_count++;
        !           332:                                        m->absent = FALSE;
        !           333:                                } else {
        !           334:                                        if (object != first_object) {
        !           335:                                                object->paging_in_progress--;
        !           336:                                                FREE_PAGE(m);
        !           337:                                        } else {
        !           338:                                                first_m = m;
        !           339:                                                m->absent = FALSE;
        !           340:                                        }
        !           341:                                        vm_object_lock(next_object);
        !           342:                                        vm_object_unlock(object);
        !           343:                                        object = next_object;
        !           344:                                        object->paging_in_progress++;
        !           345:                                        continue;
        !           346:                                }
        !           347:                        }
        !           348: 
        !           349:                        /*
        !           350:                         *      If the desired access to this page has
        !           351:                         *      been locked out, request that it be unlocked.
        !           352:                         */
        !           353: 
        !           354:                        if (fault_type & m->page_lock) {
        !           355:                                UNLOCK_AND_DEALLOCATE;
        !           356:                                return (KERN_MEMORY_ERROR);
        !           357:                        }
        !           358: 
        !           359:                        /*
        !           360:                         *      Remove the page from the pageout daemon's
        !           361:                         *      reach while we play with it.
        !           362:                         */
        !           363: 
        !           364:                        vm_page_lock_queues();
        !           365:                        if (m->inactive) {
        !           366:                                queue_remove(&vm_page_queue_inactive, m,
        !           367:                                                vm_page_t, pageq);
        !           368:                                m->inactive = FALSE;
        !           369:                                vm_page_inactive_count--;
        !           370:                                vm_stat.reactivations++;
        !           371:                        } 
        !           372: 
        !           373:                        if (m->active) {
        !           374:                                queue_remove(&vm_page_queue_active, m,
        !           375:                                                vm_page_t, pageq);
        !           376:                                m->active = FALSE;
        !           377:                                vm_page_active_count--;
        !           378:                        }
        !           379: #if    NeXT
        !           380:                        if (m->free) {
        !           381:                                /*
        !           382:                                 * We only get here on reactivation of a free page,
        !           383:                                 * vm_page_alloc takes care of this for us in the
        !           384:                                 * typical case.
        !           385:                                 */
        !           386:                                queue_remove(&vm_page_queue_free, m,
        !           387:                                                vm_page_t, pageq);
        !           388:                                m->free = FALSE;
        !           389:                                vm_page_free_count--;
        !           390:                                vm_stat.reactivations++;
        !           391:                        }
        !           392: #endif NeXT
        !           393:                        vm_page_unlock_queues();
        !           394: 
        !           395:                        /*
        !           396:                         *      Mark page busy for other threads.
        !           397:                         */
        !           398:                        m->busy = TRUE;
        !           399:                        m->absent = FALSE;
        !           400:                        break;
        !           401:                }
        !           402: 
        !           403:                if (((object->pager != vm_pager_null) &&
        !           404:                                (!change_wiring || wired))
        !           405:                    || (object == first_object)) {
        !           406: 
        !           407:                        /*
        !           408:                         *      Allocate a new page for this object/offset
        !           409:                         *      pair.
        !           410:                         */
        !           411: 
        !           412:                        m = vm_page_alloc(object, offset);
        !           413: 
        !           414:                        if (m == VM_PAGE_NULL) {
        !           415:                                UNLOCK_AND_DEALLOCATE;
        !           416:                                VM_WAIT;
        !           417:                                goto RetryFault;
        !           418:                        }
        !           419:                }
        !           420: 
        !           421:                if ((object->pager != vm_pager_null) &&
        !           422:                                (!change_wiring || wired)) {
        !           423: #if    MACH_XP
        !           424:                        kern_return_t   rc;
        !           425: #else  MACH_XP
        !           426:                        pager_return_t  rc;
        !           427: #endif MACH_XP
        !           428: 
        !           429:                        /*
        !           430:                         *      Now that we have a busy page, we can
        !           431:                         *      release the object lock.
        !           432:                         */
        !           433:                        vm_object_unlock(object);
        !           434: 
        !           435:                        /*
        !           436:                         *      Call the pager to retrieve the data, if any,
        !           437:                         *      after releasing the lock on the map.
        !           438:                         */
        !           439:                        UNLOCK_MAP;
        !           440: 
        !           441: #if    MACH_XP
        !           442:                        m->absent = TRUE;
        !           443: 
        !           444:                        vm_stat.pageins++;
        !           445:                        if ((rc = pager_data_request(object->pager, 
        !           446:                                object->pager_request,
        !           447:                                m->offset + object->paging_offset, 
        !           448:                                PAGE_SIZE, fault_type)) != KERN_SUCCESS) {
        !           449:                                if (rc != SEND_INTERRUPTED)
        !           450:                                        kprintf("%s(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) failed, %d\n",
        !           451:                                                "pager_data_request",
        !           452:                                                object->pager,
        !           453:                                                object->pager_request,
        !           454:                                                m->offset + object->paging_offset, 
        !           455:                                                PAGE_SIZE, fault_type, rc);
        !           456:                                vm_object_lock(object);
        !           457:                                FREE_PAGE(m);
        !           458:                                UNLOCK_AND_DEALLOCATE;
        !           459:                                return((rc == SEND_INTERRUPTED) ?
        !           460:                                        KERN_SUCCESS : KERN_MEMORY_ERROR);
        !           461:                        }
        !           462:                        
        !           463:                        /*
        !           464:                         * Retry with same object/offset, since new data may
        !           465:                         * be in a different page (ie, m is meaningless at
        !           466:                         * this point).
        !           467:                         */
        !           468:                        vm_object_lock(object);
        !           469:                        continue;
        !           470: #else  MACH_XP
        !           471: #if    NeXT
        !           472:                        rc = vm_pager_get(object->pager, m, error);
        !           473: #else  NeXT
        !           474:                        rc = vm_pager_get(object->pager, m);
        !           475: #endif NeXT
        !           476:                        if (rc == PAGER_SUCCESS) {
        !           477: 
        !           478:                                /*
        !           479:                                 *      Found the page.
        !           480:                                 *      Leave it busy while we play with it.
        !           481:                                 */
        !           482:                                vm_object_lock(object);
        !           483: 
        !           484:                                /*
        !           485:                                 *      Relookup in case pager changed page.
        !           486:                                 *      Pager is responsible for disposition
        !           487:                                 *      of old page if moved.
        !           488:                                 */
        !           489:                                m = vm_page_lookup(object, offset);
        !           490: 
        !           491:                                vm_stat.pageins++;
        !           492:                                pmap_clear_modify(VM_PAGE_TO_PHYS(m));
        !           493:                                break;
        !           494:                        }
        !           495:                        if (rc == PAGER_ERROR) {
        !           496:                                /*
        !           497:                                 *      Pager had the page, but could not
        !           498:                                 *      read it.  Return error to stop caller.
        !           499:                                 */
        !           500:                                vm_object_lock(object);
        !           501:                                FREE_PAGE(m);
        !           502:                                UNLOCK_AND_DEALLOCATE;
        !           503:                                return(KERN_MEMORY_ERROR);
        !           504:                        }
        !           505: 
        !           506:                        /*
        !           507:                         *      Remove the bogus page (which does not
        !           508:                         *      exist at this object/offset); before
        !           509:                         *      doing so, we must get back our object
        !           510:                         *      lock to preserve our invariant.
        !           511:                         *
        !           512:                         *      Also wake up any other thread that may want
        !           513:                         *      to bring in this page.
        !           514:                         *
        !           515:                         *      If this is the top-level object, we must
        !           516:                         *      leave the busy page to prevent another
        !           517:                         *      thread from rushing past us, and inserting
        !           518:                         *      the page in that object at the same time
        !           519:                         *      that we are.
        !           520:                         */
        !           521: 
        !           522:                        vm_object_lock(object);
        !           523:                        if (object != first_object) {
        !           524:                                FREE_PAGE(m);
        !           525:                        }
        !           526: #endif MACH_XP
        !           527:                }
        !           528: 
        !           529:                /*
        !           530:                 * For the XP system, the only case in which we get here is if
        !           531:                 * object has no pager (or unwiring).  If the pager doesn't
        !           532:                 * have the page this is handled in the m->absent case above
        !           533:                 * (and if you change things here you should look above).
        !           534:                 */
        !           535:                if (object == first_object)
        !           536:                        first_m = m;
        !           537: 
        !           538:                /*
        !           539:                 *      Move on to the next object.  Lock the next
        !           540:                 *      object before unlocking the current one.
        !           541:                 */
        !           542: 
        !           543:                offset += object->shadow_offset;
        !           544:                next_object = object->shadow;
        !           545:                if (next_object == VM_OBJECT_NULL) {
        !           546:                        /*
        !           547:                         *      If there's no object left, fill the page
        !           548:                         *      in the top object with zeros.
        !           549:                         */
        !           550:                        if (object != first_object) {
        !           551:                                object->paging_in_progress--;
        !           552:                                vm_object_unlock(object);
        !           553: 
        !           554:                                object = first_object;
        !           555:                                offset = first_offset;
        !           556:                                m = first_m;
        !           557:                                vm_object_lock(object);
        !           558:                        }
        !           559:                        first_m = VM_PAGE_NULL;
        !           560: 
        !           561:                        vm_page_zero_fill(m);
        !           562:                        vm_stat.zero_fill_count++;
        !           563:                        m->absent = FALSE;
        !           564:                        break;
        !           565:                }
        !           566:                else {
        !           567:                        vm_object_lock(next_object);
        !           568:                        if (object != first_object)
        !           569:                                object->paging_in_progress--;
        !           570:                        vm_object_unlock(object);
        !           571:                        object = next_object;
        !           572:                        object->paging_in_progress++;
        !           573:                }
        !           574:        }
        !           575: 
        !           576:        if (m->absent || m->active || m->inactive || !m->busy)
        !           577:                panic("vm_fault: absent or active or inactive or not busy after main loop");
        !           578: 
        !           579:        /*
        !           580:         *      PAGE HAS BEEN FOUND.
        !           581:         *      [Loop invariant still holds -- the object lock
        !           582:         *      is held.]
        !           583:         */
        !           584: 
        !           585:        old_m = m;      /* save page that would be copied */
        !           586: 
        !           587:        /*
        !           588:         *      If the page is being written, but isn't
        !           589:         *      already owned by the top-level object,
        !           590:         *      we have to copy it into a new page owned
        !           591:         *      by the top-level object.
        !           592:         */
        !           593: 
        !           594:        if (object != first_object) {
        !           595:                /*
        !           596:                 *      We only really need to copy if we
        !           597:                 *      want to write it.
        !           598:                 */
        !           599: 
        !           600:                if (fault_type & VM_PROT_WRITE) {
        !           601: 
        !           602:                        /*
        !           603:                         *      If we try to collapse first_object at this
        !           604:                         *      point, we may deadlock when we try to get
        !           605:                         *      the lock on an intermediate object (since we
        !           606:                         *      have the bottom object locked).  We can't
        !           607:                         *      unlock the bottom object, because the page
        !           608:                         *      we found may move (by collapse) if we do.
        !           609:                         *
        !           610:                         *      Instead, we first copy the page.  Then, when
        !           611:                         *      we have no more use for the bottom object,
        !           612:                         *      we unlock it and try to collapse.
        !           613:                         *
        !           614:                         *      Note that we copy the page even if we didn't
        !           615:                         *      need to... that's the breaks.
        !           616:                         */
        !           617: 
        !           618:                        /*
        !           619:                         *      We already have an empty page in
        !           620:                         *      first_object - use it.
        !           621:                         */
        !           622: 
        !           623:                        vm_page_copy(m, first_m);
        !           624:                        first_m->absent = FALSE;
        !           625: 
        !           626:                        /*
        !           627:                         *      If another map is truly sharing this
        !           628:                         *      page with us, we have to flush all
        !           629:                         *      uses of the original page, since we
        !           630:                         *      can't distinguish those which want the
        !           631:                         *      original from those which need the
        !           632:                         *      new copy.
        !           633:                         */
        !           634: 
        !           635:                        vm_page_lock_queues();
        !           636:                        /*
        !           637:                         *      We first activate the page, then deactivate
        !           638:                         *      it since vm_page_deactivate will only
        !           639:                         *      deactivate active pages.
        !           640:                         */
        !           641:                        vm_page_activate(m);
        !           642:                        vm_page_deactivate(m);
        !           643:                        if (!su)
        !           644:                                pmap_remove_all(VM_PAGE_TO_PHYS(m));
        !           645:                        vm_page_unlock_queues();
        !           646: 
        !           647:                        /*
        !           648:                         *      We no longer need the old page or object.
        !           649:                         */
        !           650:                        PAGE_WAKEUP(m);
        !           651:                        object->paging_in_progress--;
        !           652:                        vm_object_unlock(object);
        !           653: 
        !           654:                        /*
        !           655:                         *      Only use the new page below...
        !           656:                         */
        !           657: 
        !           658:                        vm_stat.cow_faults++;
        !           659:                        m = first_m;
        !           660:                        object = first_object;
        !           661:                        offset = first_offset;
        !           662: 
        !           663:                        /*
        !           664:                         *      Now that we've gotten the copy out of the
        !           665:                         *      way, let's try to collapse the top object.
        !           666:                         */
        !           667:                        vm_object_lock(object);
        !           668:                        /*
        !           669:                         *      But we have to play ugly games with
        !           670:                         *      paging_in_progress to do that...
        !           671:                         */
        !           672:                        object->paging_in_progress--;
        !           673:                        vm_object_collapse(object);
        !           674:                        object->paging_in_progress++;
        !           675:                }
        !           676:                else {
        !           677:                        prot &= (~VM_PROT_WRITE);
        !           678:                        m->copy_on_write = TRUE;
        !           679:                }
        !           680:        }
        !           681: 
        !           682:        if (m->active || m->inactive)
        !           683:                panic("vm_fault: active or inactive before copy object handling");
        !           684: 
        !           685:        /*
        !           686:         *      If the page is being written, but hasn't been
        !           687:         *      copied to the copy-object, we have to copy it there.
        !           688:         */
        !           689:     RetryCopy:
        !           690:        if (first_object->copy != VM_OBJECT_NULL) {
        !           691:                vm_object_t             copy_object = first_object->copy;
        !           692:                vm_offset_t             copy_offset;
        !           693:                vm_page_t               copy_m;
        !           694: 
        !           695:                /*
        !           696:                 *      We only need to copy if we want to write it.
        !           697:                 */
        !           698:                if ((fault_type & VM_PROT_WRITE) == 0) {
        !           699:                        prot &= ~VM_PROT_WRITE;
        !           700:                        m->copy_on_write = TRUE;
        !           701:                }
        !           702:                else {
        !           703:                        /*
        !           704:                         *      Try to get the lock on the copy_object.
        !           705:                         */
        !           706:                        if (!vm_object_lock_try(copy_object)) {
        !           707:                                vm_object_unlock(object);
        !           708:                                /* should spin a bit here... */
        !           709:                                vm_object_lock(object);
        !           710:                                goto RetryCopy;
        !           711:                        }
        !           712: 
        !           713:                        /*
        !           714:                         *      Make another reference to the copy-object,
        !           715:                         *      to keep it from disappearing during the
        !           716:                         *      copy.
        !           717:                         */
        !           718:                        copy_object->ref_count++;
        !           719: 
        !           720:                        /*
        !           721:                         *      Does the page exist in the copy?
        !           722:                         */
        !           723:                        copy_offset = first_offset
        !           724:                                - copy_object->shadow_offset;
        !           725:                        copy_m = vm_page_lookup(copy_object, copy_offset);
        !           726:                        if (page_exists = (copy_m != VM_PAGE_NULL)) {
        !           727:                                if (copy_m->busy) {
        !           728:                                        kern_return_t   wait_result;
        !           729: #if SCRUBVM3
        !           730:                                        /* hint if we miss it its ok */
        !           731:                                        if (copy_m->dry_vp){
        !           732:                                            vm_page_lock_queues();
        !           733:                                            (void) vm_page_completeio(copy_m, TRUE);
        !           734:                                            vm_page_unlock_queues();
        !           735:                                        } else {
        !           736: #endif
        !           737: 
        !           738:                                            /*
        !           739:                                             *  If the page is being brought
        !           740:                                             *  in, wait for it and then retry.
        !           741:                                             */
        !           742:                                            PAGE_ASSERT_WAIT(copy_m, !change_wiring);
        !           743:                                            RELEASE_PAGE(m);
        !           744:                                            copy_object->ref_count--;
        !           745:                                            vm_object_unlock(copy_object);
        !           746:                                            UNLOCK_THINGS;
        !           747:                                            thread_block();
        !           748:                                            wait_result = current_thread()->wait_result;
        !           749:                                            vm_object_deallocate(first_object);
        !           750:                                                        /* may block */
        !           751:                                            if (wait_result != THREAD_AWAKENED)
        !           752:                                                    return(KERN_SUCCESS);
        !           753:                                            goto RetryFault;
        !           754: #if SCRUBVM3
        !           755:                                        }
        !           756: #endif
        !           757:                                }
        !           758:                        }
        !           759: 
        !           760: #if    MACH_XP
        !           761:                         else {
        !           762:                                /*
        !           763:                                 *      Allocate a page for the copy
        !           764:                                 */
        !           765:                                copy_m = vm_page_alloc(copy_object,
        !           766:                                                                copy_offset);
        !           767:                                if (copy_m == VM_PAGE_NULL) {
        !           768:                                        /*
        !           769:                                         *      Wait for a page, then retry.
        !           770:                                         */
        !           771:                                        RELEASE_PAGE(m);
        !           772:                                        copy_object->ref_count--;
        !           773:                                        vm_object_unlock(copy_object);
        !           774:                                        UNLOCK_AND_DEALLOCATE;
        !           775:                                        VM_WAIT;
        !           776:                                        goto RetryFault;
        !           777:                                }
        !           778: 
        !           779:                                /*
        !           780:                                 *      Must copy page into copy-object.
        !           781:                                 */
        !           782: 
        !           783:                                vm_page_copy(m, copy_m);
        !           784:                                m->copy_on_write = FALSE;
        !           785:                                copy_m->absent = FALSE;
        !           786:                                
        !           787:                                /*
        !           788:                                 *      If the old page was in use by any users
        !           789:                                 *      of the copy-object, it must be removed
        !           790:                                 *      from all pmaps.  (We can't know which
        !           791:                                 *      pmaps use it.)
        !           792:                                 */
        !           793: 
        !           794:                                vm_page_lock_queues();
        !           795:                                pmap_remove_all(VM_PAGE_TO_PHYS(old_m));
        !           796:                                copy_m->clean = FALSE;
        !           797:                                vm_page_unlock_queues();
        !           798: 
        !           799:                                /*
        !           800:                                 *      If there's a pager, then immediately
        !           801:                                 *      page out this page, using the "initialize"
        !           802:                                 *      option.  Else, we use the copy.
        !           803:                                 */
        !           804: 
        !           805:                                if (copy_object->pager == vm_pager_null) {
        !           806:                                        vm_page_lock_queues();
        !           807:                                        vm_page_activate(copy_m);
        !           808:                                        vm_page_unlock_queues();
        !           809:                                        PAGE_WAKEUP(copy_m);
        !           810:                                } else {
        !           811:                                        /*
        !           812:                                         *      Prepare the page for pageout:
        !           813:                                         *
        !           814:                                         *      Since it was just allocated,
        !           815:                                         *      it is not on a pageout queue, but
        !           816:                                         *      it is busy.
        !           817:                                         */
        !           818: 
        !           819:                                        copy_m->busy = FALSE;
        !           820: 
        !           821:                                        /*
        !           822:                                         *      Unlock everything except the
        !           823:                                         *      copy_object itself.
        !           824:                                         */
        !           825: 
        !           826:                                        vm_object_unlock(object);
        !           827:                                        UNLOCK_MAP;
        !           828: 
        !           829:                                        vm_pageout_page(copy_m, TRUE);
        !           830: 
        !           831:                                        /*
        !           832:                                         *      Since the pageout may have
        !           833:                                         *      temporarily dropped the
        !           834:                                         *      copy_object's lock, we
        !           835:                                         *      check whether we'll have
        !           836:                                         *      to deallocate the hard way.
        !           837:                                         */
        !           838: 
        !           839:                                        if ((copy_object->shadow != object) ||
        !           840:                                            (copy_object->ref_count == 1)) {
        !           841:                                                vm_object_unlock(copy_object);
        !           842:                                                vm_object_deallocate(copy_object);
        !           843:                                                vm_object_lock(object);
        !           844:                                                goto RetryCopy;
        !           845:                                        }
        !           846:                                        
        !           847:                                        /*
        !           848:                                         *      Pick back up the old object's
        !           849:                                         *      lock.  [It is safe to do so,
        !           850:                                         *      since it must be deeper in the
        !           851:                                         *      object tree.]
        !           852:                                         */
        !           853:                                        
        !           854:                                        vm_object_lock(object);
        !           855:                                }
        !           856:                        }
        !           857: #if    defined(lint) || defined(hc)
        !           858:                        if (++page_exists != 0)
        !           859:                                panic("lint");
        !           860: #endif defined(lint) || defined(hc)
        !           861: #else  MACH_XP
        !           862:                        /*
        !           863:                         *      If the page is not in memory (in the object)
        !           864:                         *      and the object has a pager, we have to check
        !           865:                         *      if the pager has the data in secondary
        !           866:                         *      storage.
        !           867:                         */
        !           868:                        if (!page_exists) {
        !           869: 
        !           870:                                /*
        !           871:                                 *      If we don't allocate a (blank) page
        !           872:                                 *      here... another thread could try
        !           873:                                 *      to page it in, allocate a page, and
        !           874:                                 *      then block on the busy page in its
        !           875:                                 *      shadow (first_object).  Then we'd
        !           876:                                 *      trip over the busy page after we
        !           877:                                 *      found that the copy_object's pager
        !           878:                                 *      doesn't have the page...
        !           879:                                 */
        !           880:                                copy_m = vm_page_alloc(copy_object,
        !           881:                                                                copy_offset);
        !           882:                                if (copy_m == VM_PAGE_NULL) {
        !           883:                                        /*
        !           884:                                         *      Wait for a page, then retry.
        !           885:                                         */
        !           886:                                        RELEASE_PAGE(m);
        !           887:                                        copy_object->ref_count--;
        !           888:                                        vm_object_unlock(copy_object);
        !           889:                                        UNLOCK_AND_DEALLOCATE;
        !           890:                                        VM_WAIT;
        !           891:                                        goto RetryFault;
        !           892:                                }
        !           893: 
        !           894:                                if (copy_object->pager != vm_pager_null) {
        !           895:                                        vm_object_unlock(object);
        !           896:                                        vm_object_unlock(copy_object);
        !           897:                                        UNLOCK_MAP;
        !           898: 
        !           899:                                        page_exists = vm_pager_has_page(
        !           900:                                                        copy_object->pager,
        !           901:                                                        (copy_offset + copy_object->paging_offset));
        !           902: 
        !           903:                                        vm_object_lock(copy_object);
        !           904: 
        !           905:                                        /*
        !           906:                                         * Since the map is unlocked, someone
        !           907:                                         * else could have copied this object
        !           908:                                         * and put a different copy_object
        !           909:                                         * between the two.  Or, the last
        !           910:                                         * reference to the copy-object (other
        !           911:                                         * than the one we have) may have
        !           912:                                         * disappeared - if that has happened,
        !           913:                                         * we don't need to make the copy.
        !           914:                                         */
        !           915:                                        if (copy_object->shadow != object ||
        !           916:                                            copy_object->ref_count == 1) {
        !           917:                                                /*
        !           918:                                                 *      Gaah... start over!
        !           919:                                                 */
        !           920:                                                FREE_PAGE(copy_m);
        !           921:                                                vm_object_unlock(copy_object);
        !           922:                                                vm_object_deallocate(copy_object);
        !           923:                                                        /* may block */
        !           924:                                                vm_object_lock(object);
        !           925:                                                goto RetryCopy;
        !           926:                                        }
        !           927:                                        vm_object_lock(object);
        !           928: 
        !           929:                                        if (page_exists) {
        !           930:                                                /*
        !           931:                                                 *      We didn't need the page
        !           932:                                                 */
        !           933:                                                FREE_PAGE(copy_m);
        !           934:                                        }
        !           935:                                }
        !           936:                        }
        !           937:                        if (!page_exists) {
        !           938:                                /*
        !           939:                                 *      Must copy page into copy-object.
        !           940:                                 */
        !           941:                                vm_page_copy(m, copy_m);
        !           942:                                copy_m->absent = FALSE;
        !           943: 
        !           944:                                /*
        !           945:                                 * Things to remember:
        !           946:                                 * 1. The copied page must be marked 'dirty'
        !           947:                                 *    so it will be paged out to the copy
        !           948:                                 *    object.
        !           949:                                 * 2. If the old page was in use by any users
        !           950:                                 *    of the copy-object, it must be removed
        !           951:                                 *    from all pmaps.  (We can't know which
        !           952:                                 *    pmaps use it.)
        !           953:                                 */
        !           954:                                vm_page_lock_queues();
        !           955:                                pmap_remove_all(VM_PAGE_TO_PHYS(old_m));
        !           956:                                copy_m->clean = FALSE;
        !           957:                                vm_page_activate(copy_m);       /* XXX */
        !           958:                                vm_page_unlock_queues();
        !           959: 
        !           960:                                PAGE_WAKEUP(copy_m);
        !           961:                        }
        !           962: #endif MACH_XP
        !           963:                        /*
        !           964:                         *      The reference count on copy_object must be
        !           965:                         *      at least 2: one for our extra reference,
        !           966:                         *      and at least one from the outside world
        !           967:                         *      (we checked that when we last locked
        !           968:                         *      copy_object).
        !           969:                         */
        !           970:                        copy_object->ref_count--;
        !           971:                        vm_object_unlock(copy_object);
        !           972:                        m->copy_on_write = FALSE;
        !           973:                }
        !           974:        }
        !           975: 
        !           976:        if (m->active || m->inactive)
        !           977:                panic("vm_fault: active or inactive before retrying lookup");
        !           978: 
        !           979:        /*
        !           980:         *      We must verify that the maps have not changed
        !           981:         *      since our last lookup.
        !           982:         */
        !           983: 
        !           984: #if    USE_VERSIONS
        !           985:        vm_object_unlock(object);
        !           986:        while (!vm_map_verify(map, &version)) {
        !           987:                vm_object_t     retry_object;
        !           988:                vm_offset_t     retry_offset;
        !           989:                vm_prot_t       retry_prot;
        !           990: 
        !           991:                /*
        !           992:                 *      To avoid trying to write_lock the map while another
        !           993:                 *      thread has it read_locked (in vm_map_pageable), we
        !           994:                 *      do not try for write permission.  If the page is
        !           995:                 *      still writable, we will get write permission.  If it
        !           996:                 *      is not, or has been marked needs_copy, we enter the
        !           997:                 *      mapping without write permission, and will merely
        !           998:                 *      take another fault.
        !           999:                 */
        !          1000:                result = vm_map_lookup(&map, vaddr,
        !          1001:                                fault_type & ~VM_PROT_WRITE, &version,
        !          1002:                                &retry_object, &retry_offset, &retry_prot,
        !          1003:                                &wired, &su);
        !          1004: 
        !          1005:                if (result != KERN_SUCCESS) {
        !          1006:                        RELEASE_PAGE(m);
        !          1007:                        UNLOCK_AND_DEALLOCATE;
        !          1008:                        return(result);
        !          1009:                }
        !          1010: 
        !          1011:                vm_object_unlock(retry_object);
        !          1012:                vm_object_lock(object);
        !          1013: 
        !          1014:                if ((retry_object != first_object) ||
        !          1015:                                (retry_offset != first_offset)) {
        !          1016:                        RELEASE_PAGE(m);
        !          1017:                        UNLOCK_AND_DEALLOCATE;
        !          1018:                        goto RetryFault;
        !          1019:                }
        !          1020: 
        !          1021:                /*
        !          1022:                 *      Check whether the protection has changed or the object
        !          1023:                 *      has been copied while we left the map unlocked.
        !          1024:                 *      Changing from read to write permission is OK - we leave
        !          1025:                 *      the page write-protected, and catch the write fault.
        !          1026:                 *      Changing from write to read permission means that we
        !          1027:                 *      can't mark the page write-enabled after all.
        !          1028:                 */
        !          1029:                prot &= retry_prot;
        !          1030:                if (m->copy_on_write)
        !          1031:                        prot &= ~VM_PROT_WRITE;
        !          1032: 
        !          1033:                vm_object_unlock(object);
        !          1034:        }
        !          1035:        vm_object_lock(object);
        !          1036: #else  USE_VERSIONS
        !          1037: 
        !          1038:        if (!lookup_still_valid) {
        !          1039:                vm_object_t     retry_object;
        !          1040:                vm_offset_t     retry_offset;
        !          1041:                vm_prot_t       retry_prot;
        !          1042: 
        !          1043:                /*
        !          1044:                 *      Since map entries may be pageable, make sure we can
        !          1045:                 *      take a page fault on them.
        !          1046:                 */
        !          1047:                vm_object_unlock(object);
        !          1048: 
        !          1049:                /*
        !          1050:                 *      To avoid trying to write_lock the map while another
        !          1051:                 *      thread has it read_locked (in vm_map_pageable), we
        !          1052:                 *      do not try for write permission.  If the page is
        !          1053:                 *      still writable, we will get write permission.  If it
        !          1054:                 *      is not, or has been marked needs_copy, we enter the
        !          1055:                 *      mapping without write permission, and will merely
        !          1056:                 *      take another fault.
        !          1057:                 */
        !          1058: 
        !          1059:                result = vm_map_lookup(&map, vaddr,
        !          1060:                                fault_type & ~VM_PROT_WRITE, &entry,
        !          1061:                                &retry_object, &retry_offset, &retry_prot,
        !          1062:                                &wired, &su);
        !          1063:                vm_object_lock(object);
        !          1064: 
        !          1065:                /*
        !          1066:                 *      If we don't need the page any longer, put it on the
        !          1067:                 *      active list (the easiest thing to do here).  If no
        !          1068:                 *      one needs it, pageout will grab it eventually.
        !          1069:                 */
        !          1070: 
        !          1071:                if (result != KERN_SUCCESS) {
        !          1072:                        RELEASE_PAGE(m);
        !          1073:                        UNLOCK_AND_DEALLOCATE;
        !          1074:                        return(result);
        !          1075:                }
        !          1076: 
        !          1077:                lookup_still_valid = TRUE;
        !          1078: 
        !          1079:                if ((retry_object != first_object) ||
        !          1080:                                (retry_offset != first_offset)) {
        !          1081:                        RELEASE_PAGE(m);
        !          1082:                        UNLOCK_AND_DEALLOCATE;
        !          1083:                        goto RetryFault;
        !          1084:                }
        !          1085: 
        !          1086:                /*
        !          1087:                 *      Check whether the protection has changed or the object
        !          1088:                 *      has been copied while we left the map unlocked.
        !          1089:                 *      Changing from read to write permission is OK - we leave
        !          1090:                 *      the page write-protected, and catch the write fault.
        !          1091:                 *      Changing from write to read permission means that we
        !          1092:                 *      can't mark the page write-enabled after all.
        !          1093:                 */
        !          1094:                prot &= retry_prot;
        !          1095:                if (m->copy_on_write)
        !          1096:                        prot &= ~VM_PROT_WRITE;
        !          1097:                /*
        !          1098:                 *      Can't catch write fault if page is to be wired.  This
        !          1099:                 *      should never happen because caller holds a read lock
        !          1100:                 *      on the map.
        !          1101:                 */
        !          1102:                if (wired && (prot != fault_type)) {
        !          1103:                        RELEASE_PAGE(m);
        !          1104:                        UNLOCK_AND_DEALLOCATE;
        !          1105:                        goto RetryFault;
        !          1106:                }
        !          1107:        }
        !          1108: #endif USE_VERSIONS
        !          1109: 
        !          1110:        /*
        !          1111:         * (the various bits we're fiddling with here are locked by
        !          1112:         * the object's lock)
        !          1113:         */
        !          1114: 
        !          1115:        /* XXX This distorts the meaning of the copy_on_write bit */
        !          1116: 
        !          1117:        if (prot & VM_PROT_WRITE)
        !          1118:                m->copy_on_write = FALSE;
        !          1119: 
        !          1120:        /*
        !          1121:         *      It's critically important that a wired-down page be faulted
        !          1122:         *      only once in each map for which it is wired.
        !          1123:         */
        !          1124: 
        !          1125:        if (m->active || m->inactive)
        !          1126:                panic("vm_fault: active or inactive before pmap_enter");
        !          1127: 
        !          1128:        vm_object_unlock(object);
        !          1129: 
        !          1130:        /*
        !          1131:         *      Put this page into the physical map.
        !          1132:         *      We had to do the unlock above because pmap_enter
        !          1133:         *      may cause other faults.   We don't put the
        !          1134:         *      page back on the active queue until later so
        !          1135:         *      that the page-out daemon won't find us (yet).
        !          1136:         */
        !          1137: 
        !          1138:        pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), 
        !          1139:                        prot & ~(m->page_lock), wired);
        !          1140: 
        !          1141:        /*
        !          1142:         *      If the page is not wired down, then put it where the
        !          1143:         *      pageout daemon can find it.
        !          1144:         */
        !          1145:        vm_object_lock(object);
        !          1146:        vm_page_lock_queues();
        !          1147:        if (change_wiring) {
        !          1148:                if (wired)
        !          1149:                        vm_page_wire(m);
        !          1150:                else
        !          1151:                        vm_page_unwire(m);
        !          1152:        }
        !          1153:        else
        !          1154:                vm_page_activate(m);
        !          1155:        vm_page_unlock_queues();
        !          1156: 
        !          1157:        /*
        !          1158:         *      Unlock everything, and return
        !          1159:         */
        !          1160: 
        !          1161: #if    USE_VERSIONS
        !          1162:        vm_map_verify_done(map, &version);
        !          1163: #endif USE_VERSIONS
        !          1164:        PAGE_WAKEUP(m);
        !          1165:        UNLOCK_AND_DEALLOCATE;
        !          1166: 
        !          1167:        return(KERN_SUCCESS);
        !          1168: 
        !          1169: }
        !          1170: 
        !          1171: kern_return_t  vm_fault_wire_fast();
        !          1172: 
        !          1173: /*
        !          1174:  *     vm_fault_wire:
        !          1175:  *
        !          1176:  *     Wire down a range of virtual addresses in a map.
        !          1177:  */
        !          1178: void vm_fault_wire(map, entry)
        !          1179:        vm_map_t        map;
        !          1180:        vm_map_entry_t  entry;
        !          1181: {
        !          1182: 
        !          1183:        register vm_offset_t    va;
        !          1184:        register pmap_t         pmap;
        !          1185:        register vm_offset_t    end_addr = entry->vme_end;
        !          1186: 
        !          1187:        pmap = vm_map_pmap(map);
        !          1188: 
        !          1189:        /*
        !          1190:         *      Inform the physical mapping system that the
        !          1191:         *      range of addresses may not fault, so that
        !          1192:         *      page tables and such can be locked down as well.
        !          1193:         */
        !          1194: 
        !          1195:        pmap_pageable(pmap, entry->vme_start, end_addr, FALSE);
        !          1196: 
        !          1197:        /*
        !          1198:         *      We simulate a fault to get the page and enter it
        !          1199:         *      in the physical map.
        !          1200:         */
        !          1201: 
        !          1202:        for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) {
        !          1203:                if (vm_fault_wire_fast(map, va, entry) != KERN_SUCCESS)
        !          1204:                        (void) vm_fault(map, va, VM_PROT_NONE, TRUE, 0);
        !          1205:        }
        !          1206: }
        !          1207: 
        !          1208: 
        !          1209: /*
        !          1210:  *     vm_fault_unwire:
        !          1211:  *
        !          1212:  *     Unwire a range of virtual addresses in a map.
        !          1213:  */
        !          1214: void vm_fault_unwire(map, entry)
        !          1215:        vm_map_t        map;
        !          1216:        vm_map_entry_t  entry;
        !          1217: {
        !          1218: 
        !          1219:        register vm_offset_t    va, pa;
        !          1220:        register pmap_t         pmap;
        !          1221:        register vm_offset_t    end_addr = entry->vme_end;
        !          1222: 
        !          1223:        pmap = vm_map_pmap(map);
        !          1224: 
        !          1225:        /*
        !          1226:         *      Since the pages are wired down, we must be able to
        !          1227:         *      get their mappings from the physical map system.
        !          1228:         */
        !          1229: 
        !          1230:        vm_page_lock_queues();
        !          1231: 
        !          1232:        for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) {
        !          1233:                pa = pmap_extract(pmap, va);
        !          1234:                if (pa == (vm_offset_t) 0)
        !          1235:                        continue;
        !          1236: 
        !          1237:                pmap_change_wiring(pmap, va, FALSE);
        !          1238:                vm_page_unwire(PHYS_TO_VM_PAGE(pa));
        !          1239:        }
        !          1240:        vm_page_unlock_queues();
        !          1241: 
        !          1242:        /*
        !          1243:         *      Inform the physical mapping system that the range
        !          1244:         *      of addresses may fault, so that page tables and
        !          1245:         *      such may be unwired themselves.
        !          1246:         */
        !          1247: 
        !          1248:        pmap_pageable(pmap, entry->vme_start, end_addr, TRUE);
        !          1249: 
        !          1250: }
        !          1251: 
        !          1252: /*
        !          1253:  *     Routine:
        !          1254:  *             vm_fault_copy_entry
        !          1255:  *     Function:
        !          1256:  *             Copy all of the pages from a wired-down map entry to another.
        !          1257:  *
        !          1258:  *     In/out conditions:
        !          1259:  *             The source and destination maps must be locked for write.
        !          1260:  *             The source map entry must be wired down (or be a sharing map
        !          1261:  *             entry corresponding to a main map entry that is wired down).
        !          1262:  */
        !          1263: 
        !          1264: void vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry)
        !          1265:        vm_map_t        dst_map;
        !          1266:        vm_map_t        src_map;
        !          1267:        vm_map_entry_t  dst_entry;
        !          1268:        vm_map_entry_t  src_entry;
        !          1269: {
        !          1270: 
        !          1271:        vm_object_t     dst_object;
        !          1272:        vm_object_t     src_object;
        !          1273:        vm_offset_t     dst_offset;
        !          1274:        vm_offset_t     src_offset;
        !          1275:        vm_prot_t       prot;
        !          1276:        vm_offset_t     vaddr;
        !          1277:        vm_page_t       dst_m;
        !          1278:        vm_page_t       src_m;
        !          1279: 
        !          1280: #ifdef lint
        !          1281:        src_map++;
        !          1282: #endif lint
        !          1283: 
        !          1284:        src_object = src_entry->object.vm_object;
        !          1285:        src_offset = src_entry->offset;
        !          1286: 
        !          1287:        /*
        !          1288:         *      Create the top-level object for the destination entry.
        !          1289:         *      (Doesn't actually shadow anything - we copy the pages
        !          1290:         *      directly.)
        !          1291:         */
        !          1292:        dst_object = vm_object_allocate(
        !          1293:                        (vm_size_t) (dst_entry->vme_end -
        !          1294:                                        dst_entry->vme_start));
        !          1295: 
        !          1296:        dst_entry->object.vm_object = dst_object;
        !          1297:        dst_entry->offset = 0;
        !          1298: 
        !          1299:        prot  = dst_entry->max_protection;
        !          1300: 
        !          1301:        /*
        !          1302:         *      Loop through all of the pages in the entry's range, copying
        !          1303:         *      each one from the source object (it should be there) to the
        !          1304:         *      destination object.
        !          1305:         */
        !          1306:        for (vaddr = dst_entry->vme_start, dst_offset = 0;
        !          1307:             vaddr < dst_entry->vme_end;
        !          1308:             vaddr += PAGE_SIZE, dst_offset += PAGE_SIZE) {
        !          1309: 
        !          1310:                /*
        !          1311:                 *      Allocate a page in the destination object
        !          1312:                 */
        !          1313:                vm_object_lock(dst_object);
        !          1314:                do {
        !          1315:                        dst_m = vm_page_alloc(dst_object, dst_offset);
        !          1316:                        if (dst_m == VM_PAGE_NULL) {
        !          1317:                                vm_object_unlock(dst_object);
        !          1318:                                VM_WAIT;
        !          1319:                                vm_object_lock(dst_object);
        !          1320:                        }
        !          1321:                } while (dst_m == VM_PAGE_NULL);
        !          1322: 
        !          1323:                /*
        !          1324:                 *      Find the page in the source object, and copy it in.
        !          1325:                 *      (Because the source is wired down, the page will be
        !          1326:                 *      in memory.)
        !          1327:                 */
        !          1328:                vm_object_lock(src_object);
        !          1329:                src_m = vm_page_lookup(src_object, dst_offset + src_offset);
        !          1330:                if (src_m == VM_PAGE_NULL)
        !          1331:                        panic("vm_fault_copy_wired: page missing");
        !          1332: 
        !          1333:                vm_page_copy(src_m, dst_m);
        !          1334: 
        !          1335:                /*
        !          1336:                 *      Enter it in the pmap...
        !          1337:                 */
        !          1338:                vm_object_unlock(src_object);
        !          1339:                vm_object_unlock(dst_object);
        !          1340: 
        !          1341:                pmap_enter(dst_map->pmap, vaddr, VM_PAGE_TO_PHYS(dst_m),
        !          1342:                                prot, FALSE);
        !          1343: 
        !          1344:                /*
        !          1345:                 *      Mark it no longer busy, and put it on the active list.
        !          1346:                 */
        !          1347:                vm_object_lock(dst_object);
        !          1348:                vm_page_lock_queues();
        !          1349:                vm_page_activate(dst_m);
        !          1350:                vm_page_unlock_queues();
        !          1351:                PAGE_WAKEUP(dst_m);
        !          1352:                vm_object_unlock(dst_object);
        !          1353:        }
        !          1354: 
        !          1355: }
        !          1356: 
        !          1357: 
        !          1358: /*
        !          1359:  *     vm_fault_wire_fast:
        !          1360:  *
        !          1361:  *     Handle common case of a wire down page fault at the given address.
        !          1362:  *     If successful, the page is inserted into the associated physical map.
        !          1363:  *     The map entry is passed in to avoid the overhead of a map lookup.
        !          1364:  *
        !          1365:  *     NOTE: the given address should be truncated to the
        !          1366:  *     proper page address.
        !          1367:  *
        !          1368:  *     KERN_SUCCESS is returned if the page fault is handled; otherwise,
        !          1369:  *     a standard error specifying why the fault is fatal is returned.
        !          1370:  *
        !          1371:  *     The map in question must be referenced, and remains so.
        !          1372:  *     Caller has a read lock on the map.
        !          1373:  *
        !          1374:  *     This is a stripped version of vm_fault() for wiring pages.  Anything
        !          1375:  *     other than the common case will return KERN_FAILURE, and the caller
        !          1376:  *     is expected to call vm_fault().
        !          1377:  */
        !          1378: kern_return_t vm_fault_wire_fast(map, va, entry)
        !          1379:        vm_map_t        map;
        !          1380:        vm_offset_t     va;
        !          1381:        vm_map_entry_t  entry;
        !          1382: {
        !          1383:        vm_object_t             object;
        !          1384:        vm_offset_t             offset;
        !          1385:        register vm_page_t      m;
        !          1386:        vm_prot_t               prot;
        !          1387: 
        !          1388:        vm_stat.faults++;               /* needs lock XXX */
        !          1389: /*
        !          1390:  *     Recovery actions
        !          1391:  */
        !          1392: 
        !          1393: #undef RELEASE_PAGE
        !          1394: #define        RELEASE_PAGE(m) {                               \
        !          1395:        PAGE_WAKEUP(m);                                 \
        !          1396:        vm_page_lock_queues();                          \
        !          1397:        vm_page_unwire(m);                              \
        !          1398:        vm_page_unlock_queues();                        \
        !          1399: }
        !          1400: 
        !          1401: 
        !          1402: #undef UNLOCK_THINGS
        !          1403: #define        UNLOCK_THINGS   {                               \
        !          1404:        object->paging_in_progress--;                   \
        !          1405:        vm_object_unlock(object);                       \
        !          1406: }
        !          1407: 
        !          1408: #undef UNLOCK_AND_DEALLOCATE
        !          1409: #define        UNLOCK_AND_DEALLOCATE   {                       \
        !          1410:        UNLOCK_THINGS;                                  \
        !          1411:        vm_object_deallocate(object);                   \
        !          1412: }
        !          1413: /*
        !          1414:  *     Give up and have caller do things the hard way.
        !          1415:  */
        !          1416: 
        !          1417: #define        GIVE_UP {                                       \
        !          1418:        UNLOCK_AND_DEALLOCATE;                          \
        !          1419:        return(KERN_FAILURE);                           \
        !          1420: }
        !          1421: 
        !          1422: 
        !          1423:        /*
        !          1424:         *      If this entry is not directly to a vm_object, bail out.
        !          1425:         */
        !          1426:        if ((entry->is_a_map) || (entry->is_sub_map))
        !          1427:                return(KERN_FAILURE);
        !          1428: 
        !          1429:        /*
        !          1430:         *      Find the backing store object and offset into it.
        !          1431:         */
        !          1432: 
        !          1433:        object = entry->object.vm_object;
        !          1434:        offset = va - entry->vme_start + entry->offset;
        !          1435:        prot = entry->protection;
        !          1436: 
        !          1437:        /*
        !          1438:         *      Make a reference to this object to prevent its
        !          1439:         *      disposal while we are messing with it.
        !          1440:         */
        !          1441: 
        !          1442:        vm_object_lock(object);
        !          1443:        object->ref_count++;
        !          1444:        object->paging_in_progress++;
        !          1445: 
        !          1446:        /*
        !          1447:         *      INVARIANTS (through entire routine):
        !          1448:         *
        !          1449:         *      1)      At all times, we must either have the object
        !          1450:         *              lock or a busy page in some object to prevent
        !          1451:         *              some other thread from trying to bring in
        !          1452:         *              the same page.
        !          1453:         *
        !          1454:         *      2)      Once we have a busy page, we must remove it from
        !          1455:         *              the pageout queues, so that the pageout daemon
        !          1456:         *              will not grab it away.
        !          1457:         *
        !          1458:         */
        !          1459: 
        !          1460:        /*
        !          1461:         *      Look for page in top-level object.  If it's not there or
        !          1462:         *      there's something going on, give up.
        !          1463:         */
        !          1464:        m = vm_page_lookup(object, offset);
        !          1465: #if SCRUBVM3
        !          1466:        if ((m != VM_PAGE_NULL) && (m->dry_vp)){
        !          1467:            vm_page_lock_queues();
        !          1468:            (void) vm_page_completeio(m, TRUE);
        !          1469:            vm_page_unlock_queues();
        !          1470:        }
        !          1471: #endif
        !          1472:        if ((m == VM_PAGE_NULL) || (m->busy) || (m->absent) ||
        !          1473:            (prot & m->page_lock)) {
        !          1474:                GIVE_UP;
        !          1475:        }
        !          1476: 
        !          1477:        /*
        !          1478:         *      Wire the page down now.  All bail outs beyond this
        !          1479:         *      point must unwire the page.  
        !          1480:         */
        !          1481: 
        !          1482:        vm_page_lock_queues();
        !          1483:        vm_page_wire(m);
        !          1484:        vm_page_unlock_queues();
        !          1485: 
        !          1486:        /*
        !          1487:         *      Mark page busy for other threads.
        !          1488:         */
        !          1489:        m->busy = TRUE;
        !          1490:        m->absent = FALSE;
        !          1491: 
        !          1492:        /*
        !          1493:         *      Give up if the page is being written and there's a copy object
        !          1494:         */
        !          1495:        if (object->copy != VM_OBJECT_NULL) {
        !          1496:                if ((prot & VM_PROT_WRITE) == 0) {
        !          1497:                        m->copy_on_write = TRUE;
        !          1498:                }
        !          1499:                else {
        !          1500:                        RELEASE_PAGE(m);
        !          1501:                        GIVE_UP;
        !          1502:                }
        !          1503:        }
        !          1504: 
        !          1505:        /*
        !          1506:         * (the various bits we're fiddling with here are locked by
        !          1507:         * the object's lock)
        !          1508:         */
        !          1509: 
        !          1510:        /* XXX This distorts the meaning of the copy_on_write bit */
        !          1511: 
        !          1512:        if (prot & VM_PROT_WRITE)
        !          1513:                m->copy_on_write = FALSE;
        !          1514: 
        !          1515:        /*
        !          1516:         *      Put this page into the physical map.
        !          1517:         *      We have to unlock the object because pmap_enter
        !          1518:         *      may cause other faults.   
        !          1519:         */
        !          1520:        vm_object_unlock(object);
        !          1521: 
        !          1522:        pmap_enter(map->pmap, va, VM_PAGE_TO_PHYS(m), prot , TRUE);
        !          1523: 
        !          1524:        /*
        !          1525:         *      Must relock object so that paging_in_progress can be cleared.
        !          1526:         */
        !          1527:        vm_object_lock(object);
        !          1528: 
        !          1529:        /*
        !          1530:         *      Unlock everything, and return
        !          1531:         */
        !          1532: 
        !          1533:        PAGE_WAKEUP(m);
        !          1534:        UNLOCK_AND_DEALLOCATE;
        !          1535: 
        !          1536:        return(KERN_SUCCESS);
        !          1537: 
        !          1538: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.