Annotation of Net2/vm/vm_fault.c, revision 1.1.1.3

1.1       root        1: /* 
                      2:  * Copyright (c) 1991 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * The Mach Operating System project at Carnegie-Mellon University.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)vm_fault.c  7.6 (Berkeley) 5/7/91
                     37:  *
                     38:  *
                     39:  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
                     40:  * All rights reserved.
                     41:  *
                     42:  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
                     43:  * 
                     44:  * Permission to use, copy, modify and distribute this software and
                     45:  * its documentation is hereby granted, provided that both the copyright
                     46:  * notice and this permission notice appear in all copies of the
                     47:  * software, derivative works or modified versions, and any portions
                     48:  * thereof, and that both notices appear in supporting documentation.
                     49:  * 
                     50:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
                     51:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
                     52:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     53:  * 
                     54:  * Carnegie Mellon requests users of this software to return to
                     55:  *
                     56:  *  Software Distribution Coordinator  or  [email protected]
                     57:  *  School of Computer Science
                     58:  *  Carnegie Mellon University
                     59:  *  Pittsburgh PA 15213-3890
                     60:  *
                     61:  * any improvements or extensions that they make and grant Carnegie the
                     62:  * rights to redistribute these changes.
                     63:  */
                     64: 
1.1.1.3 ! root       65: static char rcsid[] = "$Header: /cvsroot/src/sys/vm/Attic/vm_fault.c,v 1.2 1993/04/09 15:54:56 cgd Exp $";
1.1.1.2   root       66: 
1.1       root       67: /*
                     68:  *     Page fault handling module.
                     69:  */
                     70: 
                     71: #include "param.h"
                     72: 
                     73: #include "vm.h"
                     74: #include "vm_page.h"
                     75: #include "vm_pageout.h"
                     76: 
                     77: /*
                     78:  *     vm_fault:
                     79:  *
                     80:  *     Handle a page fault occuring at the given address,
                     81:  *     requiring the given permissions, in the map specified.
                     82:  *     If successful, the page is inserted into the
                     83:  *     associated physical map.
                     84:  *
                     85:  *     NOTE: the given address should be truncated to the
                     86:  *     proper page address.
                     87:  *
                     88:  *     KERN_SUCCESS is returned if the page fault is handled; otherwise,
                     89:  *     a standard error specifying why the fault is fatal is returned.
                     90:  *
                     91:  *
                     92:  *     The map in question must be referenced, and remains so.
                     93:  *     Caller may hold no locks.
                     94:  */
                     95: vm_fault(map, vaddr, fault_type, change_wiring)
                     96:        vm_map_t        map;
                     97:        vm_offset_t     vaddr;
                     98:        vm_prot_t       fault_type;
                     99:        boolean_t       change_wiring;
                    100: {
                    101:        vm_object_t             first_object;
                    102:        vm_offset_t             first_offset;
                    103:        vm_map_entry_t          entry;
                    104:        register vm_object_t    object;
                    105:        register vm_offset_t    offset;
                    106:        register vm_page_t      m;
                    107:        vm_page_t               first_m;
                    108:        vm_prot_t               prot;
                    109:        int                     result;
                    110:        boolean_t               wired;
                    111:        boolean_t               su;
                    112:        boolean_t               lookup_still_valid;
                    113:        boolean_t               page_exists;
                    114:        vm_page_t               old_m;
                    115:        vm_object_t             next_object;
                    116: 
                    117:        vm_stat.faults++;               /* needs lock XXX */
                    118: /*
                    119:  *     Recovery actions
                    120:  */
                    121: #define        FREE_PAGE(m)    {                               \
                    122:        PAGE_WAKEUP(m);                                 \
                    123:        vm_page_lock_queues();                          \
                    124:        vm_page_free(m);                                \
                    125:        vm_page_unlock_queues();                        \
                    126: }
                    127: 
                    128: #define        RELEASE_PAGE(m) {                               \
                    129:        PAGE_WAKEUP(m);                                 \
                    130:        vm_page_lock_queues();                          \
                    131:        vm_page_activate(m);                            \
                    132:        vm_page_unlock_queues();                        \
                    133: }
                    134: 
                    135: #define        UNLOCK_MAP      {                               \
                    136:        if (lookup_still_valid) {                       \
                    137:                vm_map_lookup_done(map, entry);         \
                    138:                lookup_still_valid = FALSE;             \
                    139:        }                                               \
                    140: }
                    141: 
                    142: #define        UNLOCK_THINGS   {                               \
                    143:        object->paging_in_progress--;                   \
                    144:        vm_object_unlock(object);                       \
                    145:        if (object != first_object) {                   \
                    146:                vm_object_lock(first_object);           \
                    147:                FREE_PAGE(first_m);                     \
                    148:                first_object->paging_in_progress--;     \
                    149:                vm_object_unlock(first_object);         \
                    150:        }                                               \
                    151:        UNLOCK_MAP;                                     \
                    152: }
                    153: 
                    154: #define        UNLOCK_AND_DEALLOCATE   {                       \
                    155:        UNLOCK_THINGS;                                  \
                    156:        vm_object_deallocate(first_object);             \
                    157: }
                    158: 
                    159:     RetryFault: ;
                    160: 
                    161:        /*
                    162:         *      Find the backing store object and offset into
                    163:         *      it to begin the search.
                    164:         */
                    165: 
                    166:        if ((result = vm_map_lookup(&map, vaddr, fault_type, &entry,
                    167:                        &first_object, &first_offset,
                    168:                        &prot, &wired, &su)) != KERN_SUCCESS) {
                    169:                return(result);
                    170:        }
                    171:        lookup_still_valid = TRUE;
                    172: 
                    173:        if (wired)
                    174:                fault_type = prot;
                    175: 
                    176:        first_m = NULL;
                    177: 
                    178:        /*
                    179:         *      Make a reference to this object to
                    180:         *      prevent its disposal while we are messing with
                    181:         *      it.  Once we have the reference, the map is free
                    182:         *      to be diddled.  Since objects reference their
                    183:         *      shadows (and copies), they will stay around as well.
                    184:         */
                    185: 
                    186:        vm_object_lock(first_object);
                    187: 
                    188:        first_object->ref_count++;
                    189:        first_object->paging_in_progress++;
                    190: 
                    191:        /*
                    192:         *      INVARIANTS (through entire routine):
                    193:         *
                    194:         *      1)      At all times, we must either have the object
                    195:         *              lock or a busy page in some object to prevent
                    196:         *              some other thread from trying to bring in
                    197:         *              the same page.
                    198:         *
                    199:         *              Note that we cannot hold any locks during the
                    200:         *              pager access or when waiting for memory, so
                    201:         *              we use a busy page then.
                    202:         *
                    203:         *              Note also that we aren't as concerned about
                    204:         *              more than one thead attempting to pager_data_unlock
                    205:         *              the same page at once, so we don't hold the page
                    206:         *              as busy then, but do record the highest unlock
                    207:         *              value so far.  [Unlock requests may also be delivered
                    208:         *              out of order.]
                    209:         *
                    210:         *      2)      Once we have a busy page, we must remove it from
                    211:         *              the pageout queues, so that the pageout daemon
                    212:         *              will not grab it away.
                    213:         *
                    214:         *      3)      To prevent another thread from racing us down the
                    215:         *              shadow chain and entering a new page in the top
                    216:         *              object before we do, we must keep a busy page in
                    217:         *              the top object while following the shadow chain.
                    218:         *
                    219:         *      4)      We must increment paging_in_progress on any object
                    220:         *              for which we have a busy page, to prevent
                    221:         *              vm_object_collapse from removing the busy page
                    222:         *              without our noticing.
                    223:         */
                    224: 
                    225:        /*
                    226:         *      Search for the page at object/offset.
                    227:         */
                    228: 
                    229:        object = first_object;
                    230:        offset = first_offset;
                    231: 
                    232:        /*
                    233:         *      See whether this page is resident
                    234:         */
                    235: 
                    236:        while (TRUE) {
                    237:                m = vm_page_lookup(object, offset);
                    238:                if (m != NULL) {
                    239:                        /*
                    240:                         *      If the page is being brought in,
                    241:                         *      wait for it and then retry.
                    242:                         */
                    243:                        if (m->busy) {
                    244: #ifdef DOTHREADS
                    245:                                int     wait_result;
                    246: 
                    247:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    248:                                UNLOCK_THINGS;
1.1.1.3 ! root      249: thread_wakeup(&vm_pages_needed); /* XXX! -- what does this do? */
1.1       root      250:                                thread_block();
                    251:                                wait_result = current_thread()->wait_result;
                    252:                                vm_object_deallocate(first_object);
                    253:                                if (wait_result != THREAD_AWAKENED)
                    254:                                        return(KERN_SUCCESS);
                    255:                                goto RetryFault;
                    256: #else
                    257:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    258:                                UNLOCK_THINGS;
1.1.1.2   root      259: thread_wakeup(&vm_pages_needed); /* XXX! */
1.1       root      260:                                thread_block();
                    261:                                vm_object_deallocate(first_object);
                    262:                                goto RetryFault;
                    263: #endif
                    264:                        }
                    265: 
                    266:                        if (m->absent)
                    267:                                panic("vm_fault: absent");
                    268: 
                    269:                        /*
                    270:                         *      If the desired access to this page has
                    271:                         *      been locked out, request that it be unlocked.
                    272:                         */
                    273: 
                    274:                        if (fault_type & m->page_lock) {
                    275: #ifdef DOTHREADS
                    276:                                int     wait_result;
                    277: 
                    278:                                if ((fault_type & m->unlock_request) != fault_type)
                    279:                                        panic("vm_fault: pager_data_unlock");
                    280: 
                    281:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    282:                                UNLOCK_THINGS;
1.1.1.3 ! root      283: thread_wakeup(&vm_pages_needed); /* XXX! -- what does this do? */
1.1       root      284:                                thread_block();
                    285:                                wait_result = current_thread()->wait_result;
                    286:                                vm_object_deallocate(first_object);
                    287:                                if (wait_result != THREAD_AWAKENED)
                    288:                                        return(KERN_SUCCESS);
                    289:                                goto RetryFault;
                    290: #else
                    291:                                if ((fault_type & m->unlock_request) != fault_type)
                    292:                                        panic("vm_fault: pager_data_unlock");
                    293: 
                    294:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    295:                                UNLOCK_THINGS;
1.1.1.2   root      296: thread_wakeup(&vm_pages_needed); /* XXX */
1.1       root      297:                                thread_block();
                    298:                                vm_object_deallocate(first_object);
                    299:                                goto RetryFault;
                    300: #endif
                    301:                        }
                    302: 
                    303:                        /*
                    304:                         *      Remove the page from the pageout daemon's
                    305:                         *      reach while we play with it.
                    306:                         */
                    307: 
                    308:                        vm_page_lock_queues();
                    309:                        if (m->inactive) {
                    310:                                queue_remove(&vm_page_queue_inactive, m,
                    311:                                                vm_page_t, pageq);
                    312:                                m->inactive = FALSE;
                    313:                                vm_page_inactive_count--;
                    314:                                vm_stat.reactivations++;
                    315:                        } 
                    316: 
                    317:                        if (m->active) {
                    318:                                queue_remove(&vm_page_queue_active, m,
                    319:                                                vm_page_t, pageq);
                    320:                                m->active = FALSE;
                    321:                                vm_page_active_count--;
                    322:                        }
                    323:                        vm_page_unlock_queues();
                    324: 
                    325:                        /*
                    326:                         *      Mark page busy for other threads.
                    327:                         */
                    328:                        m->busy = TRUE;
                    329:                        m->absent = FALSE;
                    330:                        break;
                    331:                }
                    332: 
                    333:                if (((object->pager != NULL) &&
                    334:                                (!change_wiring || wired))
                    335:                    || (object == first_object)) {
                    336: 
                    337:                        /*
                    338:                         *      Allocate a new page for this object/offset
                    339:                         *      pair.
                    340:                         */
                    341: 
                    342:                        m = vm_page_alloc(object, offset);
                    343: 
                    344:                        if (m == NULL) {
                    345:                                UNLOCK_AND_DEALLOCATE;
                    346:                                VM_WAIT;
                    347:                                goto RetryFault;
                    348:                        }
                    349:                }
                    350: 
                    351:                if ((object->pager != NULL) &&
                    352:                                (!change_wiring || wired)) {
                    353:                        int rv;
                    354: 
                    355:                        /*
                    356:                         *      Now that we have a busy page, we can
                    357:                         *      release the object lock.
                    358:                         */
                    359:                        vm_object_unlock(object);
                    360: 
                    361:                        /*
                    362:                         *      Call the pager to retrieve the data, if any,
                    363:                         *      after releasing the lock on the map.
                    364:                         */
                    365:                        UNLOCK_MAP;
                    366: 
                    367:                        rv = vm_pager_get(object->pager, m, TRUE);
                    368:                        if (rv == VM_PAGER_OK) {
                    369:                                /*
                    370:                                 *      Found the page.
                    371:                                 *      Leave it busy while we play with it.
                    372:                                 */
                    373:                                vm_object_lock(object);
                    374: 
                    375:                                /*
                    376:                                 *      Relookup in case pager changed page.
                    377:                                 *      Pager is responsible for disposition
                    378:                                 *      of old page if moved.
                    379:                                 */
                    380:                                m = vm_page_lookup(object, offset);
                    381: 
                    382:                                vm_stat.pageins++;
                    383:                                m->fake = FALSE;
                    384:                                pmap_clear_modify(VM_PAGE_TO_PHYS(m));
                    385:                                break;
                    386:                        }
                    387: 
                    388:                        /*
                    389:                         *      Remove the bogus page (which does not
                    390:                         *      exist at this object/offset); before
                    391:                         *      doing so, we must get back our object
                    392:                         *      lock to preserve our invariant.
                    393:                         *
                    394:                         *      Also wake up any other thread that may want
                    395:                         *      to bring in this page.
                    396:                         *
                    397:                         *      If this is the top-level object, we must
                    398:                         *      leave the busy page to prevent another
                    399:                         *      thread from rushing past us, and inserting
                    400:                         *      the page in that object at the same time
                    401:                         *      that we are.
                    402:                         */
                    403: 
                    404:                        vm_object_lock(object);
                    405:                        /*
                    406:                         * Data outside the range of the pager; an error
                    407:                         */
                    408:                        if (rv == VM_PAGER_BAD) {
                    409:                                FREE_PAGE(m);
                    410:                                UNLOCK_AND_DEALLOCATE;
                    411:                                return(KERN_PROTECTION_FAILURE); /* XXX */
                    412:                        }
                    413:                        if (object != first_object) {
                    414:                                FREE_PAGE(m);
                    415:                                /*
                    416:                                 * XXX - we cannot just fall out at this
                    417:                                 * point, m has been freed and is invalid!
                    418:                                 */
                    419:                        }
                    420:                }
                    421: 
                    422:                /*
                    423:                 * We get here if the object has no pager (or unwiring)
                    424:                 * or the pager doesn't have the page.
                    425:                 */
                    426:                if (object == first_object)
                    427:                        first_m = m;
                    428: 
                    429:                /*
                    430:                 *      Move on to the next object.  Lock the next
                    431:                 *      object before unlocking the current one.
                    432:                 */
                    433: 
                    434:                offset += object->shadow_offset;
                    435:                next_object = object->shadow;
                    436:                if (next_object == NULL) {
                    437:                        /*
                    438:                         *      If there's no object left, fill the page
                    439:                         *      in the top object with zeros.
                    440:                         */
                    441:                        if (object != first_object) {
                    442:                                object->paging_in_progress--;
                    443:                                vm_object_unlock(object);
                    444: 
                    445:                                object = first_object;
                    446:                                offset = first_offset;
                    447:                                m = first_m;
                    448:                                vm_object_lock(object);
                    449:                        }
                    450:                        first_m = NULL;
                    451: 
                    452:                        vm_page_zero_fill(m);
                    453:                        vm_stat.zero_fill_count++;
                    454:                        m->fake = FALSE;
                    455:                        m->absent = FALSE;
                    456:                        break;
                    457:                }
                    458:                else {
                    459:                        vm_object_lock(next_object);
                    460:                        if (object != first_object)
                    461:                                object->paging_in_progress--;
                    462:                        vm_object_unlock(object);
                    463:                        object = next_object;
                    464:                        object->paging_in_progress++;
                    465:                }
                    466:        }
                    467: 
                    468:        if (m->absent || m->active || m->inactive || !m->busy)
                    469:                panic("vm_fault: absent or active or inactive or not busy after main loop");
                    470: 
                    471:        /*
                    472:         *      PAGE HAS BEEN FOUND.
                    473:         *      [Loop invariant still holds -- the object lock
                    474:         *      is held.]
                    475:         */
                    476: 
                    477:        old_m = m;      /* save page that would be copied */
                    478: 
                    479:        /*
                    480:         *      If the page is being written, but isn't
                    481:         *      already owned by the top-level object,
                    482:         *      we have to copy it into a new page owned
                    483:         *      by the top-level object.
                    484:         */
                    485: 
                    486:        if (object != first_object) {
                    487:                /*
                    488:                 *      We only really need to copy if we
                    489:                 *      want to write it.
                    490:                 */
                    491: 
                    492:                if (fault_type & VM_PROT_WRITE) {
                    493: 
                    494:                        /*
                    495:                         *      If we try to collapse first_object at this
                    496:                         *      point, we may deadlock when we try to get
                    497:                         *      the lock on an intermediate object (since we
                    498:                         *      have the bottom object locked).  We can't
                    499:                         *      unlock the bottom object, because the page
                    500:                         *      we found may move (by collapse) if we do.
                    501:                         *
                    502:                         *      Instead, we first copy the page.  Then, when
                    503:                         *      we have no more use for the bottom object,
                    504:                         *      we unlock it and try to collapse.
                    505:                         *
                    506:                         *      Note that we copy the page even if we didn't
                    507:                         *      need to... that's the breaks.
                    508:                         */
                    509: 
                    510:                        /*
                    511:                         *      We already have an empty page in
                    512:                         *      first_object - use it.
                    513:                         */
                    514: 
                    515:                        vm_page_copy(m, first_m);
                    516:                        first_m->fake = FALSE;
                    517:                        first_m->absent = FALSE;
                    518: 
                    519:                        /*
                    520:                         *      If another map is truly sharing this
                    521:                         *      page with us, we have to flush all
                    522:                         *      uses of the original page, since we
                    523:                         *      can't distinguish those which want the
                    524:                         *      original from those which need the
                    525:                         *      new copy.
                    526:                         *
                    527:                         *      XXX If we know that only one map has
                    528:                         *      access to this page, then we could
                    529:                         *      avoid the pmap_page_protect() call.
                    530:                         */
                    531: 
                    532:                        vm_page_lock_queues();
1.1.1.3 ! root      533:                        vm_page_activate(m);
1.1       root      534:                        pmap_page_protect(VM_PAGE_TO_PHYS(m), VM_PROT_NONE);
                    535:                        vm_page_unlock_queues();
                    536: 
                    537:                        /*
                    538:                         *      We no longer need the old page or object.
                    539:                         */
                    540:                        PAGE_WAKEUP(m);
                    541:                        object->paging_in_progress--;
                    542:                        vm_object_unlock(object);
                    543: 
                    544:                        /*
                    545:                         *      Only use the new page below...
                    546:                         */
                    547: 
                    548:                        vm_stat.cow_faults++;
                    549:                        m = first_m;
                    550:                        object = first_object;
                    551:                        offset = first_offset;
                    552: 
                    553:                        /*
                    554:                         *      Now that we've gotten the copy out of the
                    555:                         *      way, let's try to collapse the top object.
                    556:                         */
                    557:                        vm_object_lock(object);
                    558:                        /*
                    559:                         *      But we have to play ugly games with
                    560:                         *      paging_in_progress to do that...
                    561:                         */
                    562:                        object->paging_in_progress--;
                    563:                        vm_object_collapse(object);
                    564:                        object->paging_in_progress++;
                    565:                }
                    566:                else {
                    567:                        prot &= (~VM_PROT_WRITE);
                    568:                        m->copy_on_write = TRUE;
                    569:                }
                    570:        }
                    571: 
                    572:        if (m->active || m->inactive)
                    573:                panic("vm_fault: active or inactive before copy object handling");
                    574: 
                    575:        /*
                    576:         *      If the page is being written, but hasn't been
                    577:         *      copied to the copy-object, we have to copy it there.
                    578:         */
                    579:     RetryCopy:
                    580:        if (first_object->copy != NULL) {
                    581:                vm_object_t copy_object = first_object->copy;
                    582:                vm_offset_t copy_offset;
                    583:                vm_page_t copy_m;
                    584: 
                    585:                /*
                    586:                 *      We only need to copy if we want to write it.
                    587:                 */
                    588:                if ((fault_type & VM_PROT_WRITE) == 0) {
                    589:                        prot &= ~VM_PROT_WRITE;
                    590:                        m->copy_on_write = TRUE;
                    591:                }
                    592:                else {
                    593:                        /*
                    594:                         *      Try to get the lock on the copy_object.
                    595:                         */
                    596:                        if (!vm_object_lock_try(copy_object)) {
                    597:                                vm_object_unlock(object);
                    598:                                /* should spin a bit here... */
                    599:                                vm_object_lock(object);
                    600:                                goto RetryCopy;
                    601:                        }
                    602: 
                    603:                        /*
                    604:                         *      Make another reference to the copy-object,
                    605:                         *      to keep it from disappearing during the
                    606:                         *      copy.
                    607:                         */
                    608:                        copy_object->ref_count++;
                    609: 
                    610:                        /*
                    611:                         *      Does the page exist in the copy?
                    612:                         */
                    613:                        copy_offset = first_offset
                    614:                                - copy_object->shadow_offset;
                    615:                        copy_m = vm_page_lookup(copy_object, copy_offset);
                    616:                        if (page_exists = (copy_m != NULL)) {
                    617:                                if (copy_m->busy) {
                    618: #ifdef DOTHREADS
                    619:                                        int     wait_result;
                    620: 
                    621:                                        /*
                    622:                                         *      If the page is being brought
                    623:                                         *      in, wait for it and then retry.
                    624:                                         */
                    625:                                        PAGE_ASSERT_WAIT(copy_m, !change_wiring);
                    626:                                        RELEASE_PAGE(m);
                    627:                                        copy_object->ref_count--;
                    628:                                        vm_object_unlock(copy_object);
                    629:                                        UNLOCK_THINGS;
1.1.1.3 ! root      630: thread_wakeup(&vm_pages_needed); /* XXX! -- what does this do? */
1.1       root      631:                                        thread_block();
                    632:                                        wait_result = current_thread()->wait_result;
                    633:                                        vm_object_deallocate(first_object);
                    634:                                        if (wait_result != THREAD_AWAKENED)
                    635:                                                return(KERN_SUCCESS);
                    636:                                        goto RetryFault;
                    637: #else
                    638:                                        /*
                    639:                                         *      If the page is being brought
                    640:                                         *      in, wait for it and then retry.
                    641:                                         */
                    642:                                        PAGE_ASSERT_WAIT(copy_m, !change_wiring);
                    643:                                        RELEASE_PAGE(m);
                    644:                                        copy_object->ref_count--;
                    645:                                        vm_object_unlock(copy_object);
                    646:                                        UNLOCK_THINGS;
1.1.1.2   root      647: thread_wakeup(&vm_pages_needed); /* XXX */
1.1       root      648:                                        thread_block();
                    649:                                        vm_object_deallocate(first_object);
                    650:                                        goto RetryFault;
                    651: #endif
                    652:                                }
                    653:                        }
                    654: 
                    655:                        /*
                    656:                         *      If the page is not in memory (in the object)
                    657:                         *      and the object has a pager, we have to check
                    658:                         *      if the pager has the data in secondary
                    659:                         *      storage.
                    660:                         */
                    661:                        if (!page_exists) {
                    662: 
                    663:                                /*
                    664:                                 *      If we don't allocate a (blank) page
                    665:                                 *      here... another thread could try
                    666:                                 *      to page it in, allocate a page, and
                    667:                                 *      then block on the busy page in its
                    668:                                 *      shadow (first_object).  Then we'd
                    669:                                 *      trip over the busy page after we
                    670:                                 *      found that the copy_object's pager
                    671:                                 *      doesn't have the page...
                    672:                                 */
                    673:                                copy_m = vm_page_alloc(copy_object,
                    674:                                                                copy_offset);
                    675:                                if (copy_m == NULL) {
                    676:                                        /*
                    677:                                         *      Wait for a page, then retry.
                    678:                                         */
                    679:                                        RELEASE_PAGE(m);
                    680:                                        copy_object->ref_count--;
                    681:                                        vm_object_unlock(copy_object);
                    682:                                        UNLOCK_AND_DEALLOCATE;
                    683:                                        VM_WAIT;
                    684:                                        goto RetryFault;
                    685:                                }
                    686: 
                    687:                                if (copy_object->pager != NULL) {
                    688:                                        vm_object_unlock(object);
                    689:                                        vm_object_unlock(copy_object);
                    690:                                        UNLOCK_MAP;
                    691: 
                    692:                                        page_exists = vm_pager_has_page(
                    693:                                                        copy_object->pager,
                    694:                                                        (copy_offset + copy_object->paging_offset));
                    695: 
                    696:                                        vm_object_lock(copy_object);
                    697: 
                    698:                                        /*
                    699:                                         * Since the map is unlocked, someone
                    700:                                         * else could have copied this object
                    701:                                         * and put a different copy_object
                    702:                                         * between the two.  Or, the last
                    703:                                         * reference to the copy-object (other
                    704:                                         * than the one we have) may have
                    705:                                         * disappeared - if that has happened,
                    706:                                         * we don't need to make the copy.
                    707:                                         */
                    708:                                        if (copy_object->shadow != object ||
                    709:                                            copy_object->ref_count == 1) {
                    710:                                                /*
                    711:                                                 *      Gaah... start over!
                    712:                                                 */
                    713:                                                FREE_PAGE(copy_m);
                    714:                                                vm_object_unlock(copy_object);
                    715:                                                vm_object_deallocate(copy_object);
                    716:                                                        /* may block */
                    717:                                                vm_object_lock(object);
                    718:                                                goto RetryCopy;
                    719:                                        }
                    720:                                        vm_object_lock(object);
                    721: 
                    722:                                        if (page_exists) {
                    723:                                                /*
                    724:                                                 *      We didn't need the page
                    725:                                                 */
                    726:                                                FREE_PAGE(copy_m);
                    727:                                        }
                    728:                                }
                    729:                        }
                    730:                        if (!page_exists) {
                    731:                                /*
                    732:                                 *      Must copy page into copy-object.
                    733:                                 */
                    734:                                vm_page_copy(m, copy_m);
                    735:                                copy_m->fake = FALSE;
                    736:                                copy_m->absent = FALSE;
                    737: 
                    738:                                /*
                    739:                                 * Things to remember:
                    740:                                 * 1. The copied page must be marked 'dirty'
                    741:                                 *    so it will be paged out to the copy
                    742:                                 *    object.
                    743:                                 * 2. If the old page was in use by any users
                    744:                                 *    of the copy-object, it must be removed
                    745:                                 *    from all pmaps.  (We can't know which
                    746:                                 *    pmaps use it.)
                    747:                                 */
                    748:                                vm_page_lock_queues();
                    749:                                pmap_page_protect(VM_PAGE_TO_PHYS(old_m),
                    750:                                                  VM_PROT_NONE);
                    751:                                copy_m->clean = FALSE;
                    752:                                vm_page_activate(copy_m);       /* XXX */
                    753:                                vm_page_unlock_queues();
                    754: 
                    755:                                PAGE_WAKEUP(copy_m);
                    756:                        }
                    757:                        /*
                    758:                         *      The reference count on copy_object must be
                    759:                         *      at least 2: one for our extra reference,
                    760:                         *      and at least one from the outside world
                    761:                         *      (we checked that when we last locked
                    762:                         *      copy_object).
                    763:                         */
                    764:                        copy_object->ref_count--;
                    765:                        vm_object_unlock(copy_object);
                    766:                        m->copy_on_write = FALSE;
                    767:                }
                    768:        }
                    769: 
                    770:        if (m->active || m->inactive)
                    771:                panic("vm_fault: active or inactive before retrying lookup");
                    772: 
                    773:        /*
                    774:         *      We must verify that the maps have not changed
                    775:         *      since our last lookup.
                    776:         */
                    777: 
                    778:        if (!lookup_still_valid) {
                    779:                vm_object_t     retry_object;
                    780:                vm_offset_t     retry_offset;
                    781:                vm_prot_t       retry_prot;
                    782: 
                    783:                /*
                    784:                 *      Since map entries may be pageable, make sure we can
                    785:                 *      take a page fault on them.
                    786:                 */
                    787:                vm_object_unlock(object);
                    788: 
                    789:                /*
                    790:                 *      To avoid trying to write_lock the map while another
                    791:                 *      thread has it read_locked (in vm_map_pageable), we
                    792:                 *      do not try for write permission.  If the page is
                    793:                 *      still writable, we will get write permission.  If it
                    794:                 *      is not, or has been marked needs_copy, we enter the
                    795:                 *      mapping without write permission, and will merely
                    796:                 *      take another fault.
                    797:                 */
                    798:                result = vm_map_lookup(&map, vaddr,
                    799:                                fault_type & ~VM_PROT_WRITE, &entry,
                    800:                                &retry_object, &retry_offset, &retry_prot,
                    801:                                &wired, &su);
                    802: 
                    803:                vm_object_lock(object);
                    804: 
                    805:                /*
                    806:                 *      If we don't need the page any longer, put it on the
                    807:                 *      active list (the easiest thing to do here).  If no
                    808:                 *      one needs it, pageout will grab it eventually.
                    809:                 */
                    810: 
                    811:                if (result != KERN_SUCCESS) {
                    812:                        RELEASE_PAGE(m);
                    813:                        UNLOCK_AND_DEALLOCATE;
                    814:                        return(result);
                    815:                }
                    816: 
                    817:                lookup_still_valid = TRUE;
                    818: 
                    819:                if ((retry_object != first_object) ||
                    820:                                (retry_offset != first_offset)) {
                    821:                        RELEASE_PAGE(m);
                    822:                        UNLOCK_AND_DEALLOCATE;
                    823:                        goto RetryFault;
                    824:                }
                    825: 
                    826:                /*
                    827:                 *      Check whether the protection has changed or the object
                    828:                 *      has been copied while we left the map unlocked.
                    829:                 *      Changing from read to write permission is OK - we leave
                    830:                 *      the page write-protected, and catch the write fault.
                    831:                 *      Changing from write to read permission means that we
                    832:                 *      can't mark the page write-enabled after all.
                    833:                 */
                    834:                prot &= retry_prot;
                    835:                if (m->copy_on_write)
                    836:                        prot &= ~VM_PROT_WRITE;
                    837:        }
                    838: 
                    839:        /*
                    840:         * (the various bits we're fiddling with here are locked by
                    841:         * the object's lock)
                    842:         */
                    843: 
                    844:        /* XXX This distorts the meaning of the copy_on_write bit */
                    845: 
                    846:        if (prot & VM_PROT_WRITE)
                    847:                m->copy_on_write = FALSE;
                    848: 
                    849:        /*
                    850:         *      It's critically important that a wired-down page be faulted
                    851:         *      only once in each map for which it is wired.
                    852:         */
                    853: 
                    854:        if (m->active || m->inactive)
                    855:                panic("vm_fault: active or inactive before pmap_enter");
                    856: 
                    857:        vm_object_unlock(object);
                    858: 
                    859:        /*
                    860:         *      Put this page into the physical map.
                    861:         *      We had to do the unlock above because pmap_enter
                    862:         *      may cause other faults.   We don't put the
                    863:         *      page back on the active queue until later so
                    864:         *      that the page-out daemon won't find us (yet).
                    865:         */
                    866: 
                    867:        pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), 
                    868:                        prot & ~(m->page_lock), wired);
                    869: 
                    870:        /*
                    871:         *      If the page is not wired down, then put it where the
                    872:         *      pageout daemon can find it.
                    873:         */
                    874:        vm_object_lock(object);
                    875:        vm_page_lock_queues();
                    876:        if (change_wiring) {
                    877:                if (wired)
                    878:                        vm_page_wire(m);
                    879:                else
                    880:                        vm_page_unwire(m);
                    881:        }
                    882:        else
                    883:                vm_page_activate(m);
                    884:        vm_page_unlock_queues();
                    885: 
                    886:        /*
                    887:         *      Unlock everything, and return
                    888:         */
                    889: 
                    890:        PAGE_WAKEUP(m);
                    891:        UNLOCK_AND_DEALLOCATE;
                    892: 
                    893:        return(KERN_SUCCESS);
                    894: 
                    895: }
                    896: 
                    897: /*
                    898:  *     vm_fault_wire:
                    899:  *
                    900:  *     Wire down a range of virtual addresses in a map.
                    901:  */
                    902: void vm_fault_wire(map, start, end)
                    903:        vm_map_t        map;
                    904:        vm_offset_t     start, end;
                    905: {
                    906: 
                    907:        register vm_offset_t    va;
                    908:        register pmap_t         pmap;
                    909: 
                    910:        pmap = vm_map_pmap(map);
                    911: 
                    912:        /*
                    913:         *      Inform the physical mapping system that the
                    914:         *      range of addresses may not fault, so that
                    915:         *      page tables and such can be locked down as well.
                    916:         */
                    917: 
                    918:        pmap_pageable(pmap, start, end, FALSE);
                    919: 
                    920:        /*
                    921:         *      We simulate a fault to get the page and enter it
                    922:         *      in the physical map.
                    923:         */
                    924: 
                    925:        for (va = start; va < end; va += PAGE_SIZE) {
                    926:                (void) vm_fault(map, va, VM_PROT_NONE, TRUE);
                    927:        }
                    928: }
                    929: 
                    930: 
                    931: /*
                    932:  *     vm_fault_unwire:
                    933:  *
                    934:  *     Unwire a range of virtual addresses in a map.
                    935:  */
                    936: void vm_fault_unwire(map, start, end)
                    937:        vm_map_t        map;
                    938:        vm_offset_t     start, end;
                    939: {
                    940: 
                    941:        register vm_offset_t    va, pa;
                    942:        register pmap_t         pmap;
                    943: 
                    944:        pmap = vm_map_pmap(map);
                    945: 
                    946:        /*
                    947:         *      Since the pages are wired down, we must be able to
                    948:         *      get their mappings from the physical map system.
                    949:         */
                    950: 
                    951:        vm_page_lock_queues();
                    952: 
                    953:        for (va = start; va < end; va += PAGE_SIZE) {
                    954:                pa = pmap_extract(pmap, va);
                    955:                if (pa == (vm_offset_t) 0) {
                    956:                        panic("unwire: page not in pmap");
                    957:                }
                    958:                pmap_change_wiring(pmap, va, FALSE);
                    959:                vm_page_unwire(PHYS_TO_VM_PAGE(pa));
                    960:        }
                    961:        vm_page_unlock_queues();
                    962: 
                    963:        /*
                    964:         *      Inform the physical mapping system that the range
                    965:         *      of addresses may fault, so that page tables and
                    966:         *      such may be unwired themselves.
                    967:         */
                    968: 
                    969:        pmap_pageable(pmap, start, end, TRUE);
                    970: 
                    971: }
                    972: 
                    973: /*
                    974:  *     Routine:
                    975:  *             vm_fault_copy_entry
                    976:  *     Function:
                    977:  *             Copy all of the pages from a wired-down map entry to another.
                    978:  *
                    979:  *     In/out conditions:
                    980:  *             The source and destination maps must be locked for write.
                    981:  *             The source map entry must be wired down (or be a sharing map
                    982:  *             entry corresponding to a main map entry that is wired down).
                    983:  */
                    984: 
                    985: void vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry)
                    986:        vm_map_t        dst_map;
                    987:        vm_map_t        src_map;
                    988:        vm_map_entry_t  dst_entry;
                    989:        vm_map_entry_t  src_entry;
                    990: {
                    991: 
                    992:        vm_object_t     dst_object;
                    993:        vm_object_t     src_object;
                    994:        vm_offset_t     dst_offset;
                    995:        vm_offset_t     src_offset;
                    996:        vm_prot_t       prot;
                    997:        vm_offset_t     vaddr;
                    998:        vm_page_t       dst_m;
                    999:        vm_page_t       src_m;
                   1000: 
                   1001: #ifdef lint
                   1002:        src_map++;
                   1003: #endif lint
                   1004: 
                   1005:        src_object = src_entry->object.vm_object;
                   1006:        src_offset = src_entry->offset;
                   1007: 
                   1008:        /*
                   1009:         *      Create the top-level object for the destination entry.
                   1010:         *      (Doesn't actually shadow anything - we copy the pages
                   1011:         *      directly.)
                   1012:         */
                   1013:        dst_object = vm_object_allocate(
                   1014:                        (vm_size_t) (dst_entry->end - dst_entry->start));
                   1015: 
                   1016:        dst_entry->object.vm_object = dst_object;
                   1017:        dst_entry->offset = 0;
                   1018: 
                   1019:        prot  = dst_entry->max_protection;
                   1020: 
                   1021:        /*
                   1022:         *      Loop through all of the pages in the entry's range, copying
                   1023:         *      each one from the source object (it should be there) to the
                   1024:         *      destination object.
                   1025:         */
                   1026:        for (vaddr = dst_entry->start, dst_offset = 0;
                   1027:             vaddr < dst_entry->end;
                   1028:             vaddr += PAGE_SIZE, dst_offset += PAGE_SIZE) {
                   1029: 
                   1030:                /*
                   1031:                 *      Allocate a page in the destination object
                   1032:                 */
                   1033:                vm_object_lock(dst_object);
                   1034:                do {
                   1035:                        dst_m = vm_page_alloc(dst_object, dst_offset);
                   1036:                        if (dst_m == NULL) {
                   1037:                                vm_object_unlock(dst_object);
                   1038:                                VM_WAIT;
                   1039:                                vm_object_lock(dst_object);
                   1040:                        }
                   1041:                } while (dst_m == NULL);
                   1042: 
                   1043:                /*
                   1044:                 *      Find the page in the source object, and copy it in.
                   1045:                 *      (Because the source is wired down, the page will be
                   1046:                 *      in memory.)
                   1047:                 */
                   1048:                vm_object_lock(src_object);
                   1049:                src_m = vm_page_lookup(src_object, dst_offset + src_offset);
                   1050:                if (src_m == NULL)
                   1051:                        panic("vm_fault_copy_wired: page missing");
                   1052: 
                   1053:                vm_page_copy(src_m, dst_m);
                   1054: 
                   1055:                /*
                   1056:                 *      Enter it in the pmap...
                   1057:                 */
                   1058:                vm_object_unlock(src_object);
                   1059:                vm_object_unlock(dst_object);
                   1060: 
                   1061:                pmap_enter(dst_map->pmap, vaddr, VM_PAGE_TO_PHYS(dst_m),
                   1062:                                prot, FALSE);
                   1063: 
                   1064:                /*
                   1065:                 *      Mark it no longer busy, and put it on the active list.
                   1066:                 */
                   1067:                vm_object_lock(dst_object);
                   1068:                vm_page_lock_queues();
                   1069:                vm_page_activate(dst_m);
                   1070:                vm_page_unlock_queues();
                   1071:                PAGE_WAKEUP(dst_m);
                   1072:                vm_object_unlock(dst_object);
                   1073:        }
                   1074: 
                   1075: }

unix.superglobalmegacorp.com

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