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

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:  *
1.1.1.4 ! root       36:  *     from: @(#)vm_fault.c    7.6 (Berkeley) 5/7/91
        !            37:  *     vm_fault.c,v 1.6.2.1 1993/07/25 21:25:21 cgd Exp
1.1       root       38:  *
                     39:  *
                     40:  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
                     41:  * All rights reserved.
                     42:  *
                     43:  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
                     44:  * 
                     45:  * Permission to use, copy, modify and distribute this software and
                     46:  * its documentation is hereby granted, provided that both the copyright
                     47:  * notice and this permission notice appear in all copies of the
                     48:  * software, derivative works or modified versions, and any portions
                     49:  * thereof, and that both notices appear in supporting documentation.
                     50:  * 
                     51:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
                     52:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
                     53:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     54:  * 
                     55:  * Carnegie Mellon requests users of this software to return to
                     56:  *
                     57:  *  Software Distribution Coordinator  or  [email protected]
                     58:  *  School of Computer Science
                     59:  *  Carnegie Mellon University
                     60:  *  Pittsburgh PA 15213-3890
                     61:  *
                     62:  * any improvements or extensions that they make and grant Carnegie the
                     63:  * rights to redistribute these changes.
                     64:  */
                     65: 
                     66: /*
                     67:  *     Page fault handling module.
                     68:  */
                     69: 
                     70: #include "param.h"
                     71: 
                     72: #include "vm.h"
                     73: #include "vm_page.h"
                     74: #include "vm_pageout.h"
                     75: 
                     76: /*
                     77:  *     vm_fault:
                     78:  *
                     79:  *     Handle a page fault occuring at the given address,
                     80:  *     requiring the given permissions, in the map specified.
                     81:  *     If successful, the page is inserted into the
                     82:  *     associated physical map.
                     83:  *
                     84:  *     NOTE: the given address should be truncated to the
                     85:  *     proper page address.
                     86:  *
                     87:  *     KERN_SUCCESS is returned if the page fault is handled; otherwise,
                     88:  *     a standard error specifying why the fault is fatal is returned.
                     89:  *
                     90:  *
                     91:  *     The map in question must be referenced, and remains so.
                     92:  *     Caller may hold no locks.
                     93:  */
1.1.1.4 ! root       94: int
1.1       root       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;
                    249:                                thread_block();
                    250:                                wait_result = current_thread()->wait_result;
                    251:                                vm_object_deallocate(first_object);
                    252:                                if (wait_result != THREAD_AWAKENED)
                    253:                                        return(KERN_SUCCESS);
                    254:                                goto RetryFault;
                    255: #else
                    256:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    257:                                UNLOCK_THINGS;
1.1.1.2   root      258: thread_wakeup(&vm_pages_needed); /* XXX! */
1.1       root      259:                                thread_block();
                    260:                                vm_object_deallocate(first_object);
                    261:                                goto RetryFault;
                    262: #endif
                    263:                        }
                    264: 
                    265:                        if (m->absent)
                    266:                                panic("vm_fault: absent");
                    267: 
                    268:                        /*
                    269:                         *      If the desired access to this page has
                    270:                         *      been locked out, request that it be unlocked.
                    271:                         */
                    272: 
                    273:                        if (fault_type & m->page_lock) {
                    274: #ifdef DOTHREADS
                    275:                                int     wait_result;
                    276: 
                    277:                                if ((fault_type & m->unlock_request) != fault_type)
                    278:                                        panic("vm_fault: pager_data_unlock");
                    279: 
                    280:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    281:                                UNLOCK_THINGS;
                    282:                                thread_block();
                    283:                                wait_result = current_thread()->wait_result;
                    284:                                vm_object_deallocate(first_object);
                    285:                                if (wait_result != THREAD_AWAKENED)
                    286:                                        return(KERN_SUCCESS);
                    287:                                goto RetryFault;
                    288: #else
                    289:                                if ((fault_type & m->unlock_request) != fault_type)
                    290:                                        panic("vm_fault: pager_data_unlock");
                    291: 
                    292:                                PAGE_ASSERT_WAIT(m, !change_wiring);
                    293:                                UNLOCK_THINGS;
1.1.1.2   root      294: thread_wakeup(&vm_pages_needed); /* XXX */
1.1       root      295:                                thread_block();
                    296:                                vm_object_deallocate(first_object);
                    297:                                goto RetryFault;
                    298: #endif
                    299:                        }
                    300: 
                    301:                        /*
                    302:                         *      Remove the page from the pageout daemon's
                    303:                         *      reach while we play with it.
                    304:                         */
                    305: 
                    306:                        vm_page_lock_queues();
                    307:                        if (m->inactive) {
                    308:                                queue_remove(&vm_page_queue_inactive, m,
                    309:                                                vm_page_t, pageq);
                    310:                                m->inactive = FALSE;
                    311:                                vm_page_inactive_count--;
                    312:                                vm_stat.reactivations++;
                    313:                        } 
                    314: 
                    315:                        if (m->active) {
                    316:                                queue_remove(&vm_page_queue_active, m,
                    317:                                                vm_page_t, pageq);
                    318:                                m->active = FALSE;
                    319:                                vm_page_active_count--;
                    320:                        }
                    321:                        vm_page_unlock_queues();
                    322: 
                    323:                        /*
                    324:                         *      Mark page busy for other threads.
                    325:                         */
                    326:                        m->busy = TRUE;
                    327:                        m->absent = FALSE;
                    328:                        break;
                    329:                }
                    330: 
                    331:                if (((object->pager != NULL) &&
                    332:                                (!change_wiring || wired))
                    333:                    || (object == first_object)) {
                    334: 
                    335:                        /*
                    336:                         *      Allocate a new page for this object/offset
                    337:                         *      pair.
                    338:                         */
                    339: 
                    340:                        m = vm_page_alloc(object, offset);
                    341: 
                    342:                        if (m == NULL) {
                    343:                                UNLOCK_AND_DEALLOCATE;
                    344:                                VM_WAIT;
                    345:                                goto RetryFault;
                    346:                        }
                    347:                }
                    348: 
                    349:                if ((object->pager != NULL) &&
                    350:                                (!change_wiring || wired)) {
                    351:                        int rv;
                    352: 
                    353:                        /*
                    354:                         *      Now that we have a busy page, we can
                    355:                         *      release the object lock.
                    356:                         */
                    357:                        vm_object_unlock(object);
                    358: 
                    359:                        /*
                    360:                         *      Call the pager to retrieve the data, if any,
                    361:                         *      after releasing the lock on the map.
                    362:                         */
                    363:                        UNLOCK_MAP;
                    364: 
                    365:                        rv = vm_pager_get(object->pager, m, TRUE);
                    366:                        if (rv == VM_PAGER_OK) {
                    367:                                /*
                    368:                                 *      Found the page.
                    369:                                 *      Leave it busy while we play with it.
                    370:                                 */
                    371:                                vm_object_lock(object);
                    372: 
                    373:                                /*
                    374:                                 *      Relookup in case pager changed page.
                    375:                                 *      Pager is responsible for disposition
                    376:                                 *      of old page if moved.
                    377:                                 */
                    378:                                m = vm_page_lookup(object, offset);
                    379: 
                    380:                                vm_stat.pageins++;
                    381:                                m->fake = FALSE;
                    382:                                pmap_clear_modify(VM_PAGE_TO_PHYS(m));
                    383:                                break;
                    384:                        }
                    385: 
                    386:                        /*
                    387:                         *      Remove the bogus page (which does not
                    388:                         *      exist at this object/offset); before
                    389:                         *      doing so, we must get back our object
                    390:                         *      lock to preserve our invariant.
                    391:                         *
                    392:                         *      Also wake up any other thread that may want
                    393:                         *      to bring in this page.
                    394:                         *
                    395:                         *      If this is the top-level object, we must
                    396:                         *      leave the busy page to prevent another
                    397:                         *      thread from rushing past us, and inserting
                    398:                         *      the page in that object at the same time
                    399:                         *      that we are.
                    400:                         */
                    401: 
                    402:                        vm_object_lock(object);
                    403:                        /*
                    404:                         * Data outside the range of the pager; an error
                    405:                         */
                    406:                        if (rv == VM_PAGER_BAD) {
                    407:                                FREE_PAGE(m);
                    408:                                UNLOCK_AND_DEALLOCATE;
                    409:                                return(KERN_PROTECTION_FAILURE); /* XXX */
                    410:                        }
                    411:                        if (object != first_object) {
                    412:                                FREE_PAGE(m);
                    413:                                /*
                    414:                                 * XXX - we cannot just fall out at this
                    415:                                 * point, m has been freed and is invalid!
                    416:                                 */
                    417:                        }
                    418:                }
                    419: 
                    420:                /*
                    421:                 * We get here if the object has no pager (or unwiring)
                    422:                 * or the pager doesn't have the page.
                    423:                 */
                    424:                if (object == first_object)
                    425:                        first_m = m;
                    426: 
                    427:                /*
                    428:                 *      Move on to the next object.  Lock the next
                    429:                 *      object before unlocking the current one.
                    430:                 */
                    431: 
                    432:                offset += object->shadow_offset;
                    433:                next_object = object->shadow;
                    434:                if (next_object == NULL) {
                    435:                        /*
                    436:                         *      If there's no object left, fill the page
                    437:                         *      in the top object with zeros.
                    438:                         */
                    439:                        if (object != first_object) {
                    440:                                object->paging_in_progress--;
                    441:                                vm_object_unlock(object);
                    442: 
                    443:                                object = first_object;
                    444:                                offset = first_offset;
                    445:                                m = first_m;
                    446:                                vm_object_lock(object);
                    447:                        }
                    448:                        first_m = NULL;
                    449: 
                    450:                        vm_page_zero_fill(m);
                    451:                        vm_stat.zero_fill_count++;
                    452:                        m->fake = FALSE;
                    453:                        m->absent = FALSE;
                    454:                        break;
                    455:                }
                    456:                else {
                    457:                        vm_object_lock(next_object);
                    458:                        if (object != first_object)
                    459:                                object->paging_in_progress--;
                    460:                        vm_object_unlock(object);
                    461:                        object = next_object;
                    462:                        object->paging_in_progress++;
                    463:                }
                    464:        }
                    465: 
                    466:        if (m->absent || m->active || m->inactive || !m->busy)
                    467:                panic("vm_fault: absent or active or inactive or not busy after main loop");
                    468: 
                    469:        /*
                    470:         *      PAGE HAS BEEN FOUND.
                    471:         *      [Loop invariant still holds -- the object lock
                    472:         *      is held.]
                    473:         */
                    474: 
                    475:        old_m = m;      /* save page that would be copied */
                    476: 
                    477:        /*
                    478:         *      If the page is being written, but isn't
                    479:         *      already owned by the top-level object,
                    480:         *      we have to copy it into a new page owned
                    481:         *      by the top-level object.
                    482:         */
                    483: 
                    484:        if (object != first_object) {
                    485:                /*
                    486:                 *      We only really need to copy if we
                    487:                 *      want to write it.
                    488:                 */
                    489: 
                    490:                if (fault_type & VM_PROT_WRITE) {
                    491: 
                    492:                        /*
                    493:                         *      If we try to collapse first_object at this
                    494:                         *      point, we may deadlock when we try to get
                    495:                         *      the lock on an intermediate object (since we
                    496:                         *      have the bottom object locked).  We can't
                    497:                         *      unlock the bottom object, because the page
                    498:                         *      we found may move (by collapse) if we do.
                    499:                         *
                    500:                         *      Instead, we first copy the page.  Then, when
                    501:                         *      we have no more use for the bottom object,
                    502:                         *      we unlock it and try to collapse.
                    503:                         *
                    504:                         *      Note that we copy the page even if we didn't
                    505:                         *      need to... that's the breaks.
                    506:                         */
                    507: 
                    508:                        /*
                    509:                         *      We already have an empty page in
                    510:                         *      first_object - use it.
                    511:                         */
                    512: 
                    513:                        vm_page_copy(m, first_m);
                    514:                        first_m->fake = FALSE;
                    515:                        first_m->absent = FALSE;
                    516: 
                    517:                        /*
                    518:                         *      If another map is truly sharing this
                    519:                         *      page with us, we have to flush all
                    520:                         *      uses of the original page, since we
                    521:                         *      can't distinguish those which want the
                    522:                         *      original from those which need the
                    523:                         *      new copy.
                    524:                         *
                    525:                         *      XXX If we know that only one map has
                    526:                         *      access to this page, then we could
                    527:                         *      avoid the pmap_page_protect() call.
                    528:                         */
                    529: 
                    530:                        vm_page_lock_queues();
1.1.1.3   root      531:                        vm_page_activate(m);
1.1.1.4 ! root      532:                        vm_page_deactivate(m);
1.1       root      533:                        pmap_page_protect(VM_PAGE_TO_PHYS(m), VM_PROT_NONE);
                    534:                        vm_page_unlock_queues();
                    535: 
                    536:                        /*
                    537:                         *      We no longer need the old page or object.
                    538:                         */
                    539:                        PAGE_WAKEUP(m);
                    540:                        object->paging_in_progress--;
                    541:                        vm_object_unlock(object);
                    542: 
                    543:                        /*
                    544:                         *      Only use the new page below...
                    545:                         */
                    546: 
                    547:                        vm_stat.cow_faults++;
                    548:                        m = first_m;
                    549:                        object = first_object;
                    550:                        offset = first_offset;
                    551: 
                    552:                        /*
                    553:                         *      Now that we've gotten the copy out of the
                    554:                         *      way, let's try to collapse the top object.
                    555:                         */
                    556:                        vm_object_lock(object);
                    557:                        /*
                    558:                         *      But we have to play ugly games with
                    559:                         *      paging_in_progress to do that...
                    560:                         */
                    561:                        object->paging_in_progress--;
                    562:                        vm_object_collapse(object);
                    563:                        object->paging_in_progress++;
                    564:                }
                    565:                else {
                    566:                        prot &= (~VM_PROT_WRITE);
                    567:                        m->copy_on_write = TRUE;
                    568:                }
                    569:        }
                    570: 
                    571:        if (m->active || m->inactive)
                    572:                panic("vm_fault: active or inactive before copy object handling");
                    573: 
                    574:        /*
                    575:         *      If the page is being written, but hasn't been
                    576:         *      copied to the copy-object, we have to copy it there.
                    577:         */
                    578:     RetryCopy:
                    579:        if (first_object->copy != NULL) {
                    580:                vm_object_t copy_object = first_object->copy;
                    581:                vm_offset_t copy_offset;
                    582:                vm_page_t copy_m;
                    583: 
                    584:                /*
                    585:                 *      We only need to copy if we want to write it.
                    586:                 */
                    587:                if ((fault_type & VM_PROT_WRITE) == 0) {
                    588:                        prot &= ~VM_PROT_WRITE;
                    589:                        m->copy_on_write = TRUE;
                    590:                }
                    591:                else {
                    592:                        /*
                    593:                         *      Try to get the lock on the copy_object.
                    594:                         */
                    595:                        if (!vm_object_lock_try(copy_object)) {
                    596:                                vm_object_unlock(object);
                    597:                                /* should spin a bit here... */
                    598:                                vm_object_lock(object);
                    599:                                goto RetryCopy;
                    600:                        }
                    601: 
                    602:                        /*
                    603:                         *      Make another reference to the copy-object,
                    604:                         *      to keep it from disappearing during the
                    605:                         *      copy.
                    606:                         */
                    607:                        copy_object->ref_count++;
                    608: 
                    609:                        /*
                    610:                         *      Does the page exist in the copy?
                    611:                         */
                    612:                        copy_offset = first_offset
                    613:                                - copy_object->shadow_offset;
                    614:                        copy_m = vm_page_lookup(copy_object, copy_offset);
                    615:                        if (page_exists = (copy_m != NULL)) {
                    616:                                if (copy_m->busy) {
                    617: #ifdef DOTHREADS
                    618:                                        int     wait_result;
                    619: 
                    620:                                        /*
                    621:                                         *      If the page is being brought
                    622:                                         *      in, wait for it and then retry.
                    623:                                         */
                    624:                                        PAGE_ASSERT_WAIT(copy_m, !change_wiring);
                    625:                                        RELEASE_PAGE(m);
                    626:                                        copy_object->ref_count--;
                    627:                                        vm_object_unlock(copy_object);
                    628:                                        UNLOCK_THINGS;
                    629:                                        thread_block();
                    630:                                        wait_result = current_thread()->wait_result;
                    631:                                        vm_object_deallocate(first_object);
                    632:                                        if (wait_result != THREAD_AWAKENED)
                    633:                                                return(KERN_SUCCESS);
                    634:                                        goto RetryFault;
                    635: #else
                    636:                                        /*
                    637:                                         *      If the page is being brought
                    638:                                         *      in, wait for it and then retry.
                    639:                                         */
                    640:                                        PAGE_ASSERT_WAIT(copy_m, !change_wiring);
                    641:                                        RELEASE_PAGE(m);
                    642:                                        copy_object->ref_count--;
                    643:                                        vm_object_unlock(copy_object);
                    644:                                        UNLOCK_THINGS;
1.1.1.2   root      645: thread_wakeup(&vm_pages_needed); /* XXX */
1.1       root      646:                                        thread_block();
                    647:                                        vm_object_deallocate(first_object);
                    648:                                        goto RetryFault;
                    649: #endif
                    650:                                }
                    651:                        }
                    652: 
                    653:                        /*
                    654:                         *      If the page is not in memory (in the object)
                    655:                         *      and the object has a pager, we have to check
                    656:                         *      if the pager has the data in secondary
                    657:                         *      storage.
                    658:                         */
                    659:                        if (!page_exists) {
                    660: 
                    661:                                /*
                    662:                                 *      If we don't allocate a (blank) page
                    663:                                 *      here... another thread could try
                    664:                                 *      to page it in, allocate a page, and
                    665:                                 *      then block on the busy page in its
                    666:                                 *      shadow (first_object).  Then we'd
                    667:                                 *      trip over the busy page after we
                    668:                                 *      found that the copy_object's pager
                    669:                                 *      doesn't have the page...
                    670:                                 */
                    671:                                copy_m = vm_page_alloc(copy_object,
                    672:                                                                copy_offset);
                    673:                                if (copy_m == NULL) {
                    674:                                        /*
                    675:                                         *      Wait for a page, then retry.
                    676:                                         */
                    677:                                        RELEASE_PAGE(m);
                    678:                                        copy_object->ref_count--;
                    679:                                        vm_object_unlock(copy_object);
                    680:                                        UNLOCK_AND_DEALLOCATE;
                    681:                                        VM_WAIT;
                    682:                                        goto RetryFault;
                    683:                                }
                    684: 
                    685:                                if (copy_object->pager != NULL) {
                    686:                                        vm_object_unlock(object);
                    687:                                        vm_object_unlock(copy_object);
                    688:                                        UNLOCK_MAP;
                    689: 
                    690:                                        page_exists = vm_pager_has_page(
                    691:                                                        copy_object->pager,
                    692:                                                        (copy_offset + copy_object->paging_offset));
                    693: 
                    694:                                        vm_object_lock(copy_object);
                    695: 
                    696:                                        /*
                    697:                                         * Since the map is unlocked, someone
                    698:                                         * else could have copied this object
                    699:                                         * and put a different copy_object
                    700:                                         * between the two.  Or, the last
                    701:                                         * reference to the copy-object (other
                    702:                                         * than the one we have) may have
                    703:                                         * disappeared - if that has happened,
                    704:                                         * we don't need to make the copy.
                    705:                                         */
                    706:                                        if (copy_object->shadow != object ||
                    707:                                            copy_object->ref_count == 1) {
                    708:                                                /*
                    709:                                                 *      Gaah... start over!
                    710:                                                 */
                    711:                                                FREE_PAGE(copy_m);
                    712:                                                vm_object_unlock(copy_object);
                    713:                                                vm_object_deallocate(copy_object);
                    714:                                                        /* may block */
                    715:                                                vm_object_lock(object);
                    716:                                                goto RetryCopy;
                    717:                                        }
                    718:                                        vm_object_lock(object);
                    719: 
                    720:                                        if (page_exists) {
                    721:                                                /*
                    722:                                                 *      We didn't need the page
                    723:                                                 */
                    724:                                                FREE_PAGE(copy_m);
                    725:                                        }
                    726:                                }
                    727:                        }
                    728:                        if (!page_exists) {
                    729:                                /*
                    730:                                 *      Must copy page into copy-object.
                    731:                                 */
                    732:                                vm_page_copy(m, copy_m);
                    733:                                copy_m->fake = FALSE;
                    734:                                copy_m->absent = FALSE;
                    735: 
                    736:                                /*
                    737:                                 * Things to remember:
                    738:                                 * 1. The copied page must be marked 'dirty'
                    739:                                 *    so it will be paged out to the copy
                    740:                                 *    object.
                    741:                                 * 2. If the old page was in use by any users
                    742:                                 *    of the copy-object, it must be removed
                    743:                                 *    from all pmaps.  (We can't know which
                    744:                                 *    pmaps use it.)
                    745:                                 */
                    746:                                vm_page_lock_queues();
                    747:                                pmap_page_protect(VM_PAGE_TO_PHYS(old_m),
                    748:                                                  VM_PROT_NONE);
                    749:                                copy_m->clean = FALSE;
                    750:                                vm_page_activate(copy_m);       /* XXX */
                    751:                                vm_page_unlock_queues();
                    752: 
                    753:                                PAGE_WAKEUP(copy_m);
                    754:                        }
                    755:                        /*
                    756:                         *      The reference count on copy_object must be
                    757:                         *      at least 2: one for our extra reference,
                    758:                         *      and at least one from the outside world
                    759:                         *      (we checked that when we last locked
                    760:                         *      copy_object).
                    761:                         */
                    762:                        copy_object->ref_count--;
                    763:                        vm_object_unlock(copy_object);
                    764:                        m->copy_on_write = FALSE;
                    765:                }
                    766:        }
                    767: 
                    768:        if (m->active || m->inactive)
                    769:                panic("vm_fault: active or inactive before retrying lookup");
                    770: 
                    771:        /*
                    772:         *      We must verify that the maps have not changed
                    773:         *      since our last lookup.
                    774:         */
                    775: 
                    776:        if (!lookup_still_valid) {
                    777:                vm_object_t     retry_object;
                    778:                vm_offset_t     retry_offset;
                    779:                vm_prot_t       retry_prot;
                    780: 
                    781:                /*
                    782:                 *      Since map entries may be pageable, make sure we can
                    783:                 *      take a page fault on them.
                    784:                 */
                    785:                vm_object_unlock(object);
                    786: 
                    787:                /*
                    788:                 *      To avoid trying to write_lock the map while another
                    789:                 *      thread has it read_locked (in vm_map_pageable), we
                    790:                 *      do not try for write permission.  If the page is
                    791:                 *      still writable, we will get write permission.  If it
                    792:                 *      is not, or has been marked needs_copy, we enter the
                    793:                 *      mapping without write permission, and will merely
                    794:                 *      take another fault.
                    795:                 */
                    796:                result = vm_map_lookup(&map, vaddr,
                    797:                                fault_type & ~VM_PROT_WRITE, &entry,
                    798:                                &retry_object, &retry_offset, &retry_prot,
                    799:                                &wired, &su);
                    800: 
                    801:                vm_object_lock(object);
                    802: 
                    803:                /*
                    804:                 *      If we don't need the page any longer, put it on the
                    805:                 *      active list (the easiest thing to do here).  If no
                    806:                 *      one needs it, pageout will grab it eventually.
                    807:                 */
                    808: 
                    809:                if (result != KERN_SUCCESS) {
                    810:                        RELEASE_PAGE(m);
                    811:                        UNLOCK_AND_DEALLOCATE;
                    812:                        return(result);
                    813:                }
                    814: 
                    815:                lookup_still_valid = TRUE;
                    816: 
                    817:                if ((retry_object != first_object) ||
                    818:                                (retry_offset != first_offset)) {
                    819:                        RELEASE_PAGE(m);
                    820:                        UNLOCK_AND_DEALLOCATE;
                    821:                        goto RetryFault;
                    822:                }
                    823: 
                    824:                /*
                    825:                 *      Check whether the protection has changed or the object
                    826:                 *      has been copied while we left the map unlocked.
                    827:                 *      Changing from read to write permission is OK - we leave
                    828:                 *      the page write-protected, and catch the write fault.
                    829:                 *      Changing from write to read permission means that we
                    830:                 *      can't mark the page write-enabled after all.
                    831:                 */
                    832:                prot &= retry_prot;
                    833:                if (m->copy_on_write)
                    834:                        prot &= ~VM_PROT_WRITE;
                    835:        }
                    836: 
                    837:        /*
                    838:         * (the various bits we're fiddling with here are locked by
                    839:         * the object's lock)
                    840:         */
                    841: 
                    842:        /* XXX This distorts the meaning of the copy_on_write bit */
                    843: 
                    844:        if (prot & VM_PROT_WRITE)
                    845:                m->copy_on_write = FALSE;
                    846: 
                    847:        /*
                    848:         *      It's critically important that a wired-down page be faulted
                    849:         *      only once in each map for which it is wired.
                    850:         */
                    851: 
                    852:        if (m->active || m->inactive)
                    853:                panic("vm_fault: active or inactive before pmap_enter");
                    854: 
                    855:        vm_object_unlock(object);
                    856: 
                    857:        /*
                    858:         *      Put this page into the physical map.
                    859:         *      We had to do the unlock above because pmap_enter
                    860:         *      may cause other faults.   We don't put the
                    861:         *      page back on the active queue until later so
                    862:         *      that the page-out daemon won't find us (yet).
                    863:         */
                    864: 
                    865:        pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), 
                    866:                        prot & ~(m->page_lock), wired);
                    867: 
                    868:        /*
                    869:         *      If the page is not wired down, then put it where the
                    870:         *      pageout daemon can find it.
                    871:         */
                    872:        vm_object_lock(object);
                    873:        vm_page_lock_queues();
                    874:        if (change_wiring) {
                    875:                if (wired)
                    876:                        vm_page_wire(m);
                    877:                else
                    878:                        vm_page_unwire(m);
                    879:        }
                    880:        else
                    881:                vm_page_activate(m);
                    882:        vm_page_unlock_queues();
                    883: 
                    884:        /*
                    885:         *      Unlock everything, and return
                    886:         */
                    887: 
                    888:        PAGE_WAKEUP(m);
                    889:        UNLOCK_AND_DEALLOCATE;
                    890: 
                    891:        return(KERN_SUCCESS);
                    892: }
                    893: 
                    894: /*
                    895:  *     vm_fault_wire:
                    896:  *
                    897:  *     Wire down a range of virtual addresses in a map.
                    898:  */
1.1.1.4 ! root      899: void
        !           900: vm_fault_wire(map, start, end)
1.1       root      901:        vm_map_t        map;
                    902:        vm_offset_t     start, end;
                    903: {
                    904: 
                    905:        register vm_offset_t    va;
                    906:        register pmap_t         pmap;
                    907: 
                    908:        pmap = vm_map_pmap(map);
                    909: 
                    910:        /*
                    911:         *      Inform the physical mapping system that the
                    912:         *      range of addresses may not fault, so that
                    913:         *      page tables and such can be locked down as well.
                    914:         */
                    915: 
                    916:        pmap_pageable(pmap, start, end, FALSE);
                    917: 
                    918:        /*
                    919:         *      We simulate a fault to get the page and enter it
                    920:         *      in the physical map.
                    921:         */
                    922: 
                    923:        for (va = start; va < end; va += PAGE_SIZE) {
                    924:                (void) vm_fault(map, va, VM_PROT_NONE, TRUE);
                    925:        }
                    926: }
                    927: 
                    928: 
                    929: /*
                    930:  *     vm_fault_unwire:
                    931:  *
                    932:  *     Unwire a range of virtual addresses in a map.
                    933:  */
1.1.1.4 ! root      934: void
        !           935: vm_fault_unwire(map, start, end)
1.1       root      936:        vm_map_t        map;
                    937:        vm_offset_t     start, end;
                    938: {
                    939: 
                    940:        register vm_offset_t    va, pa;
                    941:        register pmap_t         pmap;
                    942: 
                    943:        pmap = vm_map_pmap(map);
                    944: 
                    945:        /*
                    946:         *      Since the pages are wired down, we must be able to
                    947:         *      get their mappings from the physical map system.
                    948:         */
                    949: 
                    950:        vm_page_lock_queues();
                    951: 
                    952:        for (va = start; va < end; va += PAGE_SIZE) {
                    953:                pa = pmap_extract(pmap, va);
                    954:                if (pa == (vm_offset_t) 0) {
                    955:                        panic("unwire: page not in pmap");
                    956:                }
                    957:                pmap_change_wiring(pmap, va, FALSE);
                    958:                vm_page_unwire(PHYS_TO_VM_PAGE(pa));
                    959:        }
                    960:        vm_page_unlock_queues();
                    961: 
                    962:        /*
                    963:         *      Inform the physical mapping system that the range
                    964:         *      of addresses may fault, so that page tables and
                    965:         *      such may be unwired themselves.
                    966:         */
                    967: 
                    968:        pmap_pageable(pmap, start, end, TRUE);
                    969: 
                    970: }
                    971: 
                    972: /*
                    973:  *     Routine:
                    974:  *             vm_fault_copy_entry
                    975:  *     Function:
                    976:  *             Copy all of the pages from a wired-down map entry to another.
                    977:  *
                    978:  *     In/out conditions:
                    979:  *             The source and destination maps must be locked for write.
                    980:  *             The source map entry must be wired down (or be a sharing map
                    981:  *             entry corresponding to a main map entry that is wired down).
                    982:  */
                    983: 
1.1.1.4 ! root      984: void
        !           985: vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry)
1.1       root      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.