Annotation of Net2/vm/vm_map.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_map.c      7.3 (Berkeley) 4/21/91
        !            37:  *     vm_map.c,v 1.6 1993/07/15 14:25:28 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:  *     Virtual memory mapping module.
                     68:  */
                     69: 
                     70: #include "param.h"
                     71: #include "malloc.h"
1.1.1.4 ! root       72: #include "systm.h"
1.1       root       73: #include "vm.h"
                     74: #include "vm_page.h"
                     75: #include "vm_object.h"
                     76: 
                     77: /*
                     78:  *     Virtual memory maps provide for the mapping, protection,
                     79:  *     and sharing of virtual memory objects.  In addition,
                     80:  *     this module provides for an efficient virtual copy of
                     81:  *     memory from one map to another.
                     82:  *
                     83:  *     Synchronization is required prior to most operations.
                     84:  *
                     85:  *     Maps consist of an ordered doubly-linked list of simple
                     86:  *     entries; a single hint is used to speed up lookups.
                     87:  *
                     88:  *     In order to properly represent the sharing of virtual
                     89:  *     memory regions among maps, the map structure is bi-level.
                     90:  *     Top-level ("address") maps refer to regions of sharable
                     91:  *     virtual memory.  These regions are implemented as
                     92:  *     ("sharing") maps, which then refer to the actual virtual
                     93:  *     memory objects.  When two address maps "share" memory,
                     94:  *     their top-level maps both have references to the same
                     95:  *     sharing map.  When memory is virtual-copied from one
                     96:  *     address map to another, the references in the sharing
                     97:  *     maps are actually copied -- no copying occurs at the
                     98:  *     virtual memory object level.
                     99:  *
                    100:  *     Since portions of maps are specified by start/end addreses,
                    101:  *     which may not align with existing map entries, all
                    102:  *     routines merely "clip" entries to these start/end values.
                    103:  *     [That is, an entry is split into two, bordering at a
                    104:  *     start or end value.]  Note that these clippings may not
                    105:  *     always be necessary (as the two resulting entries are then
                    106:  *     not changed); however, the clipping is done for convenience.
                    107:  *     No attempt is currently made to "glue back together" two
                    108:  *     abutting entries.
                    109:  *
                    110:  *     As mentioned above, virtual copy operations are performed
                    111:  *     by copying VM object references from one sharing map to
                    112:  *     another, and then marking both regions as copy-on-write.
                    113:  *     It is important to note that only one writeable reference
                    114:  *     to a VM object region exists in any map -- this means that
                    115:  *     shadow object creation can be delayed until a write operation
                    116:  *     occurs.
                    117:  */
                    118: 
1.1.1.4 ! root      119: int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t);
        !           120: 
1.1       root      121: /*
                    122:  *     vm_map_startup:
                    123:  *
                    124:  *     Initialize the vm_map module.  Must be called before
                    125:  *     any other vm_map routines.
                    126:  *
                    127:  *     Map and entry structures are allocated from the general
                    128:  *     purpose memory pool with some exceptions:
                    129:  *
                    130:  *     - The kernel map and kmem submap are allocated statically.
                    131:  *     - Kernel map entries are allocated out of a static pool.
                    132:  *
                    133:  *     These restrictions are necessary since malloc() uses the
                    134:  *     maps and requires map entries.
                    135:  */
                    136: 
                    137: vm_offset_t    kentry_data;
                    138: vm_size_t      kentry_data_size;
                    139: vm_map_entry_t kentry_free;
                    140: vm_map_t       kmap_free;
                    141: 
1.1.1.4 ! root      142: void
        !           143: vm_map_startup()
1.1       root      144: {
                    145:        register int i;
                    146:        register vm_map_entry_t mep;
                    147:        vm_map_t mp;
                    148: 
                    149:        /*
                    150:         * Static map structures for allocation before initialization of
                    151:         * kernel map or kmem map.  vm_map_create knows how to deal with them.
                    152:         */
                    153:        kmap_free = mp = (vm_map_t) kentry_data;
                    154:        i = MAX_KMAP;
                    155:        while (--i > 0) {
                    156:                mp->header.next = (vm_map_entry_t) (mp + 1);
                    157:                mp++;
                    158:        }
                    159:        mp++->header.next = NULL;
                    160: 
                    161:        /*
                    162:         * Form a free list of statically allocated kernel map entries
                    163:         * with the rest.
                    164:         */
                    165:        kentry_free = mep = (vm_map_entry_t) mp;
                    166:        i = (kentry_data_size - MAX_KMAP * sizeof *mp) / sizeof *mep;
                    167:        while (--i > 0) {
                    168:                mep->next = mep + 1;
                    169:                mep++;
                    170:        }
                    171:        mep->next = NULL;
                    172: }
                    173: 
                    174: /*
                    175:  * Allocate a vmspace structure, including a vm_map and pmap,
                    176:  * and initialize those structures.  The refcnt is set to 1.
                    177:  * The remaining fields must be initialized by the caller.
                    178:  */
                    179: struct vmspace *
                    180: vmspace_alloc(min, max, pageable)
                    181:        vm_offset_t min, max;
                    182:        int pageable;
                    183: {
                    184:        register struct vmspace *vm;
                    185: 
                    186:        MALLOC(vm, struct vmspace *, sizeof(struct vmspace), M_VMMAP, M_WAITOK);
                    187:        bzero(vm, (caddr_t) &vm->vm_startcopy - (caddr_t) vm);
                    188:        vm_map_init(&vm->vm_map, min, max, pageable);
                    189:        pmap_pinit(&vm->vm_pmap);
                    190:        vm->vm_map.pmap = &vm->vm_pmap;         /* XXX */
                    191:        vm->vm_refcnt = 1;
                    192:        return (vm);
                    193: }
                    194: 
                    195: void
                    196: vmspace_free(vm)
                    197:        register struct vmspace *vm;
                    198: {
                    199: 
                    200:        if (--vm->vm_refcnt == 0) {
                    201:                /*
                    202:                 * Lock the map, to wait out all other references to it.
                    203:                 * Delete all of the mappings and pages they hold,
                    204:                 * then call the pmap module to reclaim anything left.
                    205:                 */
                    206:                vm_map_lock(&vm->vm_map);
                    207:                (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset,
                    208:                    vm->vm_map.max_offset);
                    209:                pmap_release(&vm->vm_pmap);
                    210:                FREE(vm, M_VMMAP);
                    211:        }
                    212: }
                    213: 
                    214: /*
                    215:  *     vm_map_create:
                    216:  *
                    217:  *     Creates and returns a new empty VM map with
                    218:  *     the given physical map structure, and having
                    219:  *     the given lower and upper address bounds.
                    220:  */
                    221: vm_map_t vm_map_create(pmap, min, max, pageable)
                    222:        pmap_t          pmap;
                    223:        vm_offset_t     min, max;
                    224:        boolean_t       pageable;
                    225: {
                    226:        register vm_map_t       result;
1.1.1.4 ! root      227:        extern vm_map_t         kmem_map;
1.1       root      228: 
                    229:        if (kmem_map == NULL) {
                    230:                result = kmap_free;
                    231:                kmap_free = (vm_map_t) result->header.next;
                    232:                if (result == NULL)
                    233:                        panic("vm_map_create: out of maps");
                    234:        } else
                    235:                MALLOC(result, vm_map_t, sizeof(struct vm_map),
                    236:                       M_VMMAP, M_WAITOK);
                    237: 
                    238:        vm_map_init(result, min, max, pageable);
                    239:        result->pmap = pmap;
                    240:        return(result);
                    241: }
                    242: 
                    243: /*
                    244:  * Initialize an existing vm_map structure
                    245:  * such as that in the vmspace structure.
                    246:  * The pmap is set elsewhere.
                    247:  */
                    248: void
                    249: vm_map_init(map, min, max, pageable)
                    250:        register struct vm_map *map;
                    251:        vm_offset_t     min, max;
                    252:        boolean_t       pageable;
                    253: {
                    254:        map->header.next = map->header.prev = &map->header;
                    255:        map->nentries = 0;
                    256:        map->size = 0;
                    257:        map->ref_count = 1;
                    258:        map->is_main_map = TRUE;
                    259:        map->min_offset = min;
                    260:        map->max_offset = max;
                    261:        map->entries_pageable = pageable;
                    262:        map->first_free = &map->header;
                    263:        map->hint = &map->header;
                    264:        map->timestamp = 0;
                    265:        lock_init(&map->lock, TRUE);
                    266:        simple_lock_init(&map->ref_lock);
                    267:        simple_lock_init(&map->hint_lock);
                    268: }
                    269: 
                    270: /*
                    271:  *     vm_map_entry_create:    [ internal use only ]
                    272:  *
                    273:  *     Allocates a VM map entry for insertion.
                    274:  *     No entry fields are filled in.  This routine is
                    275:  */
                    276: vm_map_entry_t vm_map_entry_create(map)
                    277:        vm_map_t        map;
                    278: {
                    279:        vm_map_entry_t  entry;
1.1.1.4 ! root      280:        extern vm_map_t kernel_map, kmem_map, mb_map, buffer_map, pager_map;
1.1       root      281: 
1.1.1.2   root      282:        if (map == kernel_map || map == kmem_map || map == mb_map
1.1.1.3   root      283:                || map == buffer_map || map == pager_map) {
1.1       root      284:                if (entry = kentry_free)
                    285:                        kentry_free = kentry_free->next;
                    286:        } else
                    287:                MALLOC(entry, vm_map_entry_t, sizeof(struct vm_map_entry),
                    288:                       M_VMMAPENT, M_WAITOK);
                    289:        if (entry == NULL)
                    290:                panic("vm_map_entry_create: out of map entries");
                    291: 
                    292:        return(entry);
                    293: }
                    294: 
                    295: /*
                    296:  *     vm_map_entry_dispose:   [ internal use only ]
                    297:  *
                    298:  *     Inverse of vm_map_entry_create.
                    299:  */
1.1.1.4 ! root      300: void
        !           301: vm_map_entry_dispose(map, entry)
1.1       root      302:        vm_map_t        map;
                    303:        vm_map_entry_t  entry;
                    304: {
1.1.1.3   root      305:        extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map, pager_map;
1.1       root      306: 
1.1.1.2   root      307:        if (map == kernel_map || map == kmem_map || map == mb_map
1.1.1.3   root      308:                || map == buffer_map || map == pager_map) {
1.1       root      309:                entry->next = kentry_free;
                    310:                kentry_free = entry;
                    311:        } else
                    312:                FREE(entry, M_VMMAPENT);
                    313: }
                    314: 
                    315: /*
                    316:  *     vm_map_entry_{un,}link:
                    317:  *
                    318:  *     Insert/remove entries from maps.
                    319:  */
                    320: #define        vm_map_entry_link(map, after_where, entry) \
                    321:                { \
                    322:                (map)->nentries++; \
                    323:                (entry)->prev = (after_where); \
                    324:                (entry)->next = (after_where)->next; \
                    325:                (entry)->prev->next = (entry); \
                    326:                (entry)->next->prev = (entry); \
                    327:                }
                    328: #define        vm_map_entry_unlink(map, entry) \
                    329:                { \
                    330:                (map)->nentries--; \
                    331:                (entry)->next->prev = (entry)->prev; \
                    332:                (entry)->prev->next = (entry)->next; \
                    333:                }
                    334: 
                    335: /*
                    336:  *     vm_map_reference:
                    337:  *
                    338:  *     Creates another valid reference to the given map.
                    339:  *
                    340:  */
1.1.1.4 ! root      341: void
        !           342: vm_map_reference(map)
1.1       root      343:        register vm_map_t       map;
                    344: {
                    345:        if (map == NULL)
                    346:                return;
                    347: 
                    348:        simple_lock(&map->ref_lock);
                    349:        map->ref_count++;
                    350:        simple_unlock(&map->ref_lock);
                    351: }
                    352: 
                    353: /*
                    354:  *     vm_map_deallocate:
                    355:  *
                    356:  *     Removes a reference from the specified map,
                    357:  *     destroying it if no references remain.
                    358:  *     The map should not be locked.
                    359:  */
1.1.1.4 ! root      360: void
        !           361: vm_map_deallocate(map)
1.1       root      362:        register vm_map_t       map;
                    363: {
                    364:        register int            c;
                    365: 
                    366:        if (map == NULL)
                    367:                return;
                    368: 
                    369:        simple_lock(&map->ref_lock);
                    370:        c = --map->ref_count;
                    371:        simple_unlock(&map->ref_lock);
                    372: 
                    373:        if (c > 0) {
                    374:                return;
                    375:        }
                    376: 
                    377:        /*
                    378:         *      Lock the map, to wait out all other references
                    379:         *      to it.
                    380:         */
                    381: 
                    382:        vm_map_lock(map);
                    383: 
                    384:        (void) vm_map_delete(map, map->min_offset, map->max_offset);
                    385: 
                    386:        pmap_destroy(map->pmap);
                    387: 
                    388:        FREE(map, M_VMMAP);
                    389: }
                    390: 
                    391: /*
                    392:  *     vm_map_insert:  [ internal use only ]
                    393:  *
                    394:  *     Inserts the given whole VM object into the target
                    395:  *     map at the specified address range.  The object's
                    396:  *     size should match that of the address range.
                    397:  *
                    398:  *     Requires that the map be locked, and leaves it so.
                    399:  */
1.1.1.4 ! root      400: int
1.1       root      401: vm_map_insert(map, object, offset, start, end)
                    402:        vm_map_t        map;
                    403:        vm_object_t     object;
                    404:        vm_offset_t     offset;
                    405:        vm_offset_t     start;
                    406:        vm_offset_t     end;
                    407: {
                    408:        register vm_map_entry_t         new_entry;
                    409:        register vm_map_entry_t         prev_entry;
                    410:        vm_map_entry_t                  temp_entry;
                    411: 
                    412:        /*
                    413:         *      Check that the start and end points are not bogus.
                    414:         */
                    415: 
                    416:        if ((start < map->min_offset) || (end > map->max_offset) ||
                    417:                        (start >= end))
                    418:                return(KERN_INVALID_ADDRESS);
                    419: 
                    420:        /*
                    421:         *      Find the entry prior to the proposed
                    422:         *      starting address; if it's part of an
                    423:         *      existing entry, this range is bogus.
                    424:         */
                    425: 
                    426:        if (vm_map_lookup_entry(map, start, &temp_entry))
                    427:                return(KERN_NO_SPACE);
                    428: 
                    429:        prev_entry = temp_entry;
                    430: 
                    431:        /*
                    432:         *      Assert that the next entry doesn't overlap the
                    433:         *      end point.
                    434:         */
                    435: 
                    436:        if ((prev_entry->next != &map->header) &&
                    437:                        (prev_entry->next->start < end))
                    438:                return(KERN_NO_SPACE);
                    439: 
                    440:        /*
                    441:         *      See if we can avoid creating a new entry by
                    442:         *      extending one of our neighbors.
                    443:         */
                    444: 
                    445:        if (object == NULL) {
                    446:                if ((prev_entry != &map->header) &&
                    447:                    (prev_entry->end == start) &&
                    448:                    (map->is_main_map) &&
                    449:                    (prev_entry->is_a_map == FALSE) &&
                    450:                    (prev_entry->is_sub_map == FALSE) &&
                    451:                    (prev_entry->inheritance == VM_INHERIT_DEFAULT) &&
                    452:                    (prev_entry->protection == VM_PROT_DEFAULT) &&
                    453:                    (prev_entry->max_protection == VM_PROT_DEFAULT) &&
                    454:                    (prev_entry->wired_count == 0)) {
                    455: 
                    456:                        if (vm_object_coalesce(prev_entry->object.vm_object,
                    457:                                        NULL,
                    458:                                        prev_entry->offset,
                    459:                                        (vm_offset_t) 0,
                    460:                                        (vm_size_t)(prev_entry->end
                    461:                                                     - prev_entry->start),
                    462:                                        (vm_size_t)(end - prev_entry->end))) {
                    463:                                /*
                    464:                                 *      Coalesced the two objects - can extend
                    465:                                 *      the previous map entry to include the
                    466:                                 *      new range.
                    467:                                 */
                    468:                                map->size += (end - prev_entry->end);
                    469:                                prev_entry->end = end;
                    470:                                return(KERN_SUCCESS);
                    471:                        }
                    472:                }
                    473:        }
                    474: 
                    475:        /*
                    476:         *      Create a new entry
                    477:         */
                    478: 
                    479:        new_entry = vm_map_entry_create(map);
                    480:        new_entry->start = start;
                    481:        new_entry->end = end;
                    482: 
                    483:        new_entry->is_a_map = FALSE;
                    484:        new_entry->is_sub_map = FALSE;
                    485:        new_entry->object.vm_object = object;
                    486:        new_entry->offset = offset;
                    487: 
                    488:        new_entry->copy_on_write = FALSE;
                    489:        new_entry->needs_copy = FALSE;
                    490: 
                    491:        if (map->is_main_map) {
                    492:                new_entry->inheritance = VM_INHERIT_DEFAULT;
                    493:                new_entry->protection = VM_PROT_DEFAULT;
                    494:                new_entry->max_protection = VM_PROT_DEFAULT;
                    495:                new_entry->wired_count = 0;
                    496:        }
                    497: 
                    498:        /*
                    499:         *      Insert the new entry into the list
                    500:         */
                    501: 
                    502:        vm_map_entry_link(map, prev_entry, new_entry);
                    503:        map->size += new_entry->end - new_entry->start;
                    504: 
                    505:        /*
                    506:         *      Update the free space hint
                    507:         */
                    508: 
                    509:        if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start))
                    510:                map->first_free = new_entry;
                    511: 
                    512:        return(KERN_SUCCESS);
                    513: }
                    514: 
                    515: /*
                    516:  *     SAVE_HINT:
                    517:  *
                    518:  *     Saves the specified entry as the hint for
                    519:  *     future lookups.  Performs necessary interlocks.
                    520:  */
                    521: #define        SAVE_HINT(map,value) \
                    522:                simple_lock(&(map)->hint_lock); \
                    523:                (map)->hint = (value); \
                    524:                simple_unlock(&(map)->hint_lock);
                    525: 
                    526: /*
                    527:  *     vm_map_lookup_entry:    [ internal use only ]
                    528:  *
                    529:  *     Finds the map entry containing (or
                    530:  *     immediately preceding) the specified address
                    531:  *     in the given map; the entry is returned
                    532:  *     in the "entry" parameter.  The boolean
                    533:  *     result indicates whether the address is
                    534:  *     actually contained in the map.
                    535:  */
                    536: boolean_t vm_map_lookup_entry(map, address, entry)
                    537:        register vm_map_t       map;
                    538:        register vm_offset_t    address;
                    539:        vm_map_entry_t          *entry;         /* OUT */
                    540: {
                    541:        register vm_map_entry_t         cur;
                    542:        register vm_map_entry_t         last;
                    543: 
                    544:        /*
                    545:         *      Start looking either from the head of the
                    546:         *      list, or from the hint.
                    547:         */
                    548: 
                    549:        simple_lock(&map->hint_lock);
                    550:        cur = map->hint;
                    551:        simple_unlock(&map->hint_lock);
                    552: 
                    553:        if (cur == &map->header)
                    554:                cur = cur->next;
                    555: 
                    556:        if (address >= cur->start) {
                    557:                /*
                    558:                 *      Go from hint to end of list.
                    559:                 *
                    560:                 *      But first, make a quick check to see if
                    561:                 *      we are already looking at the entry we
                    562:                 *      want (which is usually the case).
                    563:                 *      Note also that we don't need to save the hint
                    564:                 *      here... it is the same hint (unless we are
                    565:                 *      at the header, in which case the hint didn't
                    566:                 *      buy us anything anyway).
                    567:                 */
                    568:                last = &map->header;
                    569:                if ((cur != last) && (cur->end > address)) {
                    570:                        *entry = cur;
                    571:                        return(TRUE);
                    572:                }
                    573:        }
                    574:        else {
                    575:                /*
                    576:                 *      Go from start to hint, *inclusively*
                    577:                 */
                    578:                last = cur->next;
                    579:                cur = map->header.next;
                    580:        }
                    581: 
                    582:        /*
                    583:         *      Search linearly
                    584:         */
                    585: 
                    586:        while (cur != last) {
                    587:                if (cur->end > address) {
                    588:                        if (address >= cur->start) {
                    589:                                /*
                    590:                                 *      Save this lookup for future
                    591:                                 *      hints, and return
                    592:                                 */
                    593: 
                    594:                                *entry = cur;
                    595:                                SAVE_HINT(map, cur);
                    596:                                return(TRUE);
                    597:                        }
                    598:                        break;
                    599:                }
                    600:                cur = cur->next;
                    601:        }
                    602:        *entry = cur->prev;
                    603:        SAVE_HINT(map, *entry);
                    604:        return(FALSE);
                    605: }
                    606: 
                    607: /*
                    608:  *     vm_map_find finds an unallocated region in the target address
                    609:  *     map with the given length.  The search is defined to be
                    610:  *     first-fit from the specified address; the region found is
                    611:  *     returned in the same parameter.
                    612:  *
                    613:  */
1.1.1.4 ! root      614: int
1.1       root      615: vm_map_find(map, object, offset, addr, length, find_space)
                    616:        vm_map_t        map;
                    617:        vm_object_t     object;
                    618:        vm_offset_t     offset;
                    619:        vm_offset_t     *addr;          /* IN/OUT */
                    620:        vm_size_t       length;
                    621:        boolean_t       find_space;
                    622: {
                    623:        register vm_map_entry_t entry;
                    624:        register vm_offset_t    start;
                    625:        register vm_offset_t    end;
                    626:        int                     result;
                    627: 
                    628:        start = *addr;
                    629: 
                    630:        vm_map_lock(map);
                    631: 
                    632:        if (find_space) {
                    633:                /*
                    634:                 *      Calculate the first possible address.
                    635:                 */
                    636: 
                    637:                if (start < map->min_offset)
                    638:                        start = map->min_offset;
                    639:                if (start > map->max_offset) {
                    640:                        vm_map_unlock(map);
                    641:                        return (KERN_NO_SPACE);
                    642:                }
                    643: 
                    644:                /*
                    645:                 *      Look for the first possible address;
                    646:                 *      if there's already something at this
                    647:                 *      address, we have to start after it.
                    648:                 */
                    649: 
                    650:                if (start == map->min_offset) {
                    651:                        if ((entry = map->first_free) != &map->header)
                    652:                                start = entry->end;
                    653:                } else {
                    654:                        vm_map_entry_t  tmp_entry;
                    655:                        if (vm_map_lookup_entry(map, start, &tmp_entry))
                    656:                                start = tmp_entry->end;
                    657:                        entry = tmp_entry;
                    658:                }
                    659: 
                    660:                /*
                    661:                 *      In any case, the "entry" always precedes
                    662:                 *      the proposed new region throughout the
                    663:                 *      loop:
                    664:                 */
                    665: 
                    666:                while (TRUE) {
                    667:                        register vm_map_entry_t next;
                    668: 
                    669:                        /*
                    670:                         *      Find the end of the proposed new region.
                    671:                         *      Be sure we didn't go beyond the end, or
                    672:                         *      wrap around the address.
                    673:                         */
                    674: 
                    675:                        end = start + length;
                    676: 
                    677:                        if ((end > map->max_offset) || (end < start)) {
                    678:                                vm_map_unlock(map);
                    679:                                return (KERN_NO_SPACE);
                    680:                        }
                    681: 
                    682:                        /*
                    683:                         *      If there are no more entries, we must win.
                    684:                         */
                    685: 
                    686:                        next = entry->next;
                    687:                        if (next == &map->header)
                    688:                                break;
                    689: 
                    690:                        /*
                    691:                         *      If there is another entry, it must be
                    692:                         *      after the end of the potential new region.
                    693:                         */
                    694: 
                    695:                        if (next->start >= end)
                    696:                                break;
                    697: 
                    698:                        /*
                    699:                         *      Didn't fit -- move to the next entry.
                    700:                         */
                    701: 
                    702:                        entry = next;
                    703:                        start = entry->end;
                    704:                }
                    705:                *addr = start;
                    706:                
                    707:                SAVE_HINT(map, entry);
                    708:        }
                    709: 
                    710:        result = vm_map_insert(map, object, offset, start, start + length);
                    711: 
                    712:        vm_map_unlock(map);
                    713:        return(result);
                    714: }
                    715: 
                    716: /*
                    717:  *     vm_map_simplify_entry:  [ internal use only ]
                    718:  *
                    719:  *     Simplify the given map entry by:
                    720:  *             removing extra sharing maps
                    721:  *             [XXX maybe later] merging with a neighbor
                    722:  */
1.1.1.4 ! root      723: void
        !           724: vm_map_simplify_entry(map, entry)
1.1       root      725:        vm_map_t        map;
                    726:        vm_map_entry_t  entry;
                    727: {
                    728: #ifdef lint
                    729:        map++;
                    730: #endif lint
                    731: 
                    732:        /*
                    733:         *      If this entry corresponds to a sharing map, then
                    734:         *      see if we can remove the level of indirection.
                    735:         *      If it's not a sharing map, then it points to
                    736:         *      a VM object, so see if we can merge with either
                    737:         *      of our neighbors.
                    738:         */
                    739: 
                    740:        if (entry->is_sub_map)
                    741:                return;
                    742:        if (entry->is_a_map) {
                    743: #if    0
                    744:                vm_map_t        my_share_map;
                    745:                int             count;
                    746: 
                    747:                my_share_map = entry->object.share_map; 
                    748:                simple_lock(&my_share_map->ref_lock);
                    749:                count = my_share_map->ref_count;
                    750:                simple_unlock(&my_share_map->ref_lock);
                    751:                
                    752:                if (count == 1) {
                    753:                        /* Can move the region from
                    754:                         * entry->start to entry->end (+ entry->offset)
                    755:                         * in my_share_map into place of entry.
                    756:                         * Later.
                    757:                         */
                    758:                }
                    759: #endif 0
                    760:        }
                    761:        else {
                    762:                /*
                    763:                 *      Try to merge with our neighbors.
                    764:                 *
                    765:                 *      Conditions for merge are:
                    766:                 *
                    767:                 *      1.  entries are adjacent.
                    768:                 *      2.  both entries point to objects
                    769:                 *          with null pagers.
                    770:                 *
                    771:                 *      If a merge is possible, we replace the two
                    772:                 *      entries with a single entry, then merge
                    773:                 *      the two objects into a single object.
                    774:                 *
                    775:                 *      Now, all that is left to do is write the
                    776:                 *      code!
                    777:                 */
                    778:        }
                    779: }
                    780: 
                    781: /*
                    782:  *     vm_map_clip_start:      [ internal use only ]
                    783:  *
                    784:  *     Asserts that the given entry begins at or after
                    785:  *     the specified address; if necessary,
                    786:  *     it splits the entry into two.
                    787:  */
                    788: #define vm_map_clip_start(map, entry, startaddr) \
                    789: { \
                    790:        if (startaddr > entry->start) \
                    791:                _vm_map_clip_start(map, entry, startaddr); \
                    792: }
                    793: 
                    794: /*
                    795:  *     This routine is called only when it is known that
                    796:  *     the entry must be split.
                    797:  */
1.1.1.4 ! root      798: void
        !           799: _vm_map_clip_start(map, entry, start)
1.1       root      800:        register vm_map_t       map;
                    801:        register vm_map_entry_t entry;
                    802:        register vm_offset_t    start;
                    803: {
                    804:        register vm_map_entry_t new_entry;
                    805: 
                    806:        /*
                    807:         *      See if we can simplify this entry first
                    808:         */
                    809:                 
                    810:        vm_map_simplify_entry(map, entry);
                    811: 
                    812:        /*
                    813:         *      Split off the front portion --
                    814:         *      note that we must insert the new
                    815:         *      entry BEFORE this one, so that
                    816:         *      this entry has the specified starting
                    817:         *      address.
                    818:         */
                    819: 
                    820:        new_entry = vm_map_entry_create(map);
                    821:        *new_entry = *entry;
                    822: 
                    823:        new_entry->end = start;
                    824:        entry->offset += (start - entry->start);
                    825:        entry->start = start;
                    826: 
                    827:        vm_map_entry_link(map, entry->prev, new_entry);
                    828: 
                    829:        if (entry->is_a_map || entry->is_sub_map)
                    830:                vm_map_reference(new_entry->object.share_map);
                    831:        else
                    832:                vm_object_reference(new_entry->object.vm_object);
                    833: }
                    834: 
                    835: /*
                    836:  *     vm_map_clip_end:        [ internal use only ]
                    837:  *
                    838:  *     Asserts that the given entry ends at or before
                    839:  *     the specified address; if necessary,
                    840:  *     it splits the entry into two.
                    841:  */
                    842: 
                    843: void _vm_map_clip_end();
                    844: #define vm_map_clip_end(map, entry, endaddr) \
                    845: { \
                    846:        if (endaddr < entry->end) \
                    847:                _vm_map_clip_end(map, entry, endaddr); \
                    848: }
                    849: 
                    850: /*
                    851:  *     This routine is called only when it is known that
                    852:  *     the entry must be split.
                    853:  */
1.1.1.4 ! root      854: void
        !           855: _vm_map_clip_end(map, entry, end)
1.1       root      856:        register vm_map_t       map;
                    857:        register vm_map_entry_t entry;
                    858:        register vm_offset_t    end;
                    859: {
                    860:        register vm_map_entry_t new_entry;
                    861: 
                    862:        /*
                    863:         *      Create a new entry and insert it
                    864:         *      AFTER the specified entry
                    865:         */
                    866: 
                    867:        new_entry = vm_map_entry_create(map);
                    868:        *new_entry = *entry;
                    869: 
                    870:        new_entry->start = entry->end = end;
                    871:        new_entry->offset += (end - entry->start);
                    872: 
                    873:        vm_map_entry_link(map, entry, new_entry);
                    874: 
                    875:        if (entry->is_a_map || entry->is_sub_map)
                    876:                vm_map_reference(new_entry->object.share_map);
                    877:        else
                    878:                vm_object_reference(new_entry->object.vm_object);
                    879: }
                    880: 
                    881: /*
                    882:  *     VM_MAP_RANGE_CHECK:     [ internal use only ]
                    883:  *
                    884:  *     Asserts that the starting and ending region
                    885:  *     addresses fall within the valid range of the map.
                    886:  */
                    887: #define        VM_MAP_RANGE_CHECK(map, start, end)             \
                    888:                {                                       \
                    889:                if (start < vm_map_min(map))            \
                    890:                        start = vm_map_min(map);        \
                    891:                if (end > vm_map_max(map))              \
                    892:                        end = vm_map_max(map);          \
                    893:                if (start > end)                        \
                    894:                        start = end;                    \
                    895:                }
                    896: 
                    897: /*
                    898:  *     vm_map_submap:          [ kernel use only ]
                    899:  *
                    900:  *     Mark the given range as handled by a subordinate map.
                    901:  *
                    902:  *     This range must have been created with vm_map_find,
                    903:  *     and no other operations may have been performed on this
                    904:  *     range prior to calling vm_map_submap.
                    905:  *
                    906:  *     Only a limited number of operations can be performed
                    907:  *     within this rage after calling vm_map_submap:
                    908:  *             vm_fault
                    909:  *     [Don't try vm_map_copy!]
                    910:  *
                    911:  *     To remove a submapping, one must first remove the
                    912:  *     range from the superior map, and then destroy the
                    913:  *     submap (if desired).  [Better yet, don't try it.]
                    914:  */
1.1.1.4 ! root      915: int
1.1       root      916: vm_map_submap(map, start, end, submap)
                    917:        register vm_map_t       map;
                    918:        register vm_offset_t    start;
                    919:        register vm_offset_t    end;
                    920:        vm_map_t                submap;
                    921: {
                    922:        vm_map_entry_t          entry;
                    923:        register int            result = KERN_INVALID_ARGUMENT;
                    924: 
                    925:        vm_map_lock(map);
                    926: 
                    927:        VM_MAP_RANGE_CHECK(map, start, end);
                    928: 
                    929:        if (vm_map_lookup_entry(map, start, &entry)) {
                    930:                vm_map_clip_start(map, entry, start);
                    931:        }
                    932:         else
                    933:                entry = entry->next;
                    934: 
                    935:        vm_map_clip_end(map, entry, end);
                    936: 
                    937:        if ((entry->start == start) && (entry->end == end) &&
                    938:            (!entry->is_a_map) &&
                    939:            (entry->object.vm_object == NULL) &&
                    940:            (!entry->copy_on_write)) {
                    941:                entry->is_a_map = FALSE;
                    942:                entry->is_sub_map = TRUE;
                    943:                vm_map_reference(entry->object.sub_map = submap);
                    944:                result = KERN_SUCCESS;
                    945:        }
                    946:        vm_map_unlock(map);
                    947: 
                    948:        return(result);
                    949: }
                    950: 
                    951: /*
                    952:  *     vm_map_protect:
                    953:  *
                    954:  *     Sets the protection of the specified address
                    955:  *     region in the target map.  If "set_max" is
                    956:  *     specified, the maximum protection is to be set;
                    957:  *     otherwise, only the current protection is affected.
                    958:  */
1.1.1.4 ! root      959: int
1.1       root      960: vm_map_protect(map, start, end, new_prot, set_max)
                    961:        register vm_map_t       map;
                    962:        register vm_offset_t    start;
                    963:        register vm_offset_t    end;
                    964:        register vm_prot_t      new_prot;
                    965:        register boolean_t      set_max;
                    966: {
                    967:        register vm_map_entry_t         current;
                    968:        vm_map_entry_t                  entry;
                    969: 
                    970:        vm_map_lock(map);
                    971: 
                    972:        VM_MAP_RANGE_CHECK(map, start, end);
                    973: 
                    974:        if (vm_map_lookup_entry(map, start, &entry)) {
                    975:                vm_map_clip_start(map, entry, start);
                    976:        }
                    977:         else
                    978:                entry = entry->next;
                    979: 
                    980:        /*
                    981:         *      Make a first pass to check for protection
                    982:         *      violations.
                    983:         */
                    984: 
                    985:        current = entry;
                    986:        while ((current != &map->header) && (current->start < end)) {
                    987:                if (current->is_sub_map)
                    988:                        return(KERN_INVALID_ARGUMENT);
                    989:                if ((new_prot & current->max_protection) != new_prot) {
                    990:                        vm_map_unlock(map);
                    991:                        return(KERN_PROTECTION_FAILURE);
                    992:                }
                    993: 
                    994:                current = current->next;
                    995:        }
                    996: 
                    997:        /*
                    998:         *      Go back and fix up protections.
                    999:         *      [Note that clipping is not necessary the second time.]
                   1000:         */
                   1001: 
                   1002:        current = entry;
                   1003: 
                   1004:        while ((current != &map->header) && (current->start < end)) {
                   1005:                vm_prot_t       old_prot;
                   1006: 
                   1007:                vm_map_clip_end(map, current, end);
                   1008: 
                   1009:                old_prot = current->protection;
                   1010:                if (set_max)
                   1011:                        current->protection =
                   1012:                                (current->max_protection = new_prot) &
                   1013:                                        old_prot;
                   1014:                else
                   1015:                        current->protection = new_prot;
                   1016: 
                   1017:                /*
                   1018:                 *      Update physical map if necessary.
                   1019:                 *      Worry about copy-on-write here -- CHECK THIS XXX
                   1020:                 */
                   1021: 
                   1022:                if (current->protection != old_prot) {
                   1023: 
                   1024: #define MASK(entry)    ((entry)->copy_on_write ? ~VM_PROT_WRITE : \
                   1025:                                                        VM_PROT_ALL)
                   1026: #define        max(a,b)        ((a) > (b) ? (a) : (b))
                   1027: 
                   1028:                        if (current->is_a_map) {
                   1029:                                vm_map_entry_t  share_entry;
                   1030:                                vm_offset_t     share_end;
                   1031: 
                   1032:                                vm_map_lock(current->object.share_map);
                   1033:                                (void) vm_map_lookup_entry(
                   1034:                                                current->object.share_map,
                   1035:                                                current->offset,
                   1036:                                                &share_entry);
                   1037:                                share_end = current->offset +
                   1038:                                        (current->end - current->start);
                   1039:                                while ((share_entry !=
                   1040:                                        &current->object.share_map->header) &&
                   1041:                                        (share_entry->start < share_end)) {
                   1042: 
                   1043:                                        pmap_protect(map->pmap,
                   1044:                                                (max(share_entry->start,
                   1045:                                                        current->offset) -
                   1046:                                                        current->offset +
                   1047:                                                        current->start),
                   1048:                                                min(share_entry->end,
                   1049:                                                        share_end) -
                   1050:                                                current->offset +
                   1051:                                                current->start,
                   1052:                                                current->protection &
                   1053:                                                        MASK(share_entry));
                   1054: 
                   1055:                                        share_entry = share_entry->next;
                   1056:                                }
                   1057:                                vm_map_unlock(current->object.share_map);
                   1058:                        }
                   1059:                        else
                   1060:                                pmap_protect(map->pmap, current->start,
                   1061:                                        current->end,
                   1062:                                        current->protection & MASK(entry));
                   1063: #undef max
                   1064: #undef MASK
                   1065:                }
                   1066:                current = current->next;
                   1067:        }
                   1068: 
                   1069:        vm_map_unlock(map);
                   1070:        return(KERN_SUCCESS);
                   1071: }
                   1072: 
                   1073: /*
                   1074:  *     vm_map_inherit:
                   1075:  *
                   1076:  *     Sets the inheritance of the specified address
                   1077:  *     range in the target map.  Inheritance
                   1078:  *     affects how the map will be shared with
                   1079:  *     child maps at the time of vm_map_fork.
                   1080:  */
1.1.1.4 ! root     1081: int
1.1       root     1082: vm_map_inherit(map, start, end, new_inheritance)
                   1083:        register vm_map_t       map;
                   1084:        register vm_offset_t    start;
                   1085:        register vm_offset_t    end;
                   1086:        register vm_inherit_t   new_inheritance;
                   1087: {
                   1088:        register vm_map_entry_t entry;
                   1089:        vm_map_entry_t  temp_entry;
                   1090: 
                   1091:        switch (new_inheritance) {
                   1092:        case VM_INHERIT_NONE:
                   1093:        case VM_INHERIT_COPY:
                   1094:        case VM_INHERIT_SHARE:
                   1095:                break;
                   1096:        default:
                   1097:                return(KERN_INVALID_ARGUMENT);
                   1098:        }
                   1099: 
                   1100:        vm_map_lock(map);
                   1101: 
                   1102:        VM_MAP_RANGE_CHECK(map, start, end);
                   1103: 
                   1104:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1105:                entry = temp_entry;
                   1106:                vm_map_clip_start(map, entry, start);
                   1107:        }
                   1108:        else
                   1109:                entry = temp_entry->next;
                   1110: 
                   1111:        while ((entry != &map->header) && (entry->start < end)) {
                   1112:                vm_map_clip_end(map, entry, end);
                   1113: 
                   1114:                entry->inheritance = new_inheritance;
                   1115: 
                   1116:                entry = entry->next;
                   1117:        }
                   1118: 
                   1119:        vm_map_unlock(map);
                   1120:        return(KERN_SUCCESS);
                   1121: }
                   1122: 
                   1123: /*
                   1124:  *     vm_map_pageable:
                   1125:  *
                   1126:  *     Sets the pageability of the specified address
                   1127:  *     range in the target map.  Regions specified
                   1128:  *     as not pageable require locked-down physical
                   1129:  *     memory and physical page maps.
                   1130:  *
                   1131:  *     The map must not be locked, but a reference
                   1132:  *     must remain to the map throughout the call.
                   1133:  */
1.1.1.4 ! root     1134: int
1.1       root     1135: vm_map_pageable(map, start, end, new_pageable)
                   1136:        register vm_map_t       map;
                   1137:        register vm_offset_t    start;
                   1138:        register vm_offset_t    end;
                   1139:        register boolean_t      new_pageable;
                   1140: {
                   1141:        register vm_map_entry_t entry;
                   1142:        vm_map_entry_t          temp_entry;
                   1143: 
                   1144:        vm_map_lock(map);
                   1145: 
                   1146:        VM_MAP_RANGE_CHECK(map, start, end);
                   1147: 
                   1148:        /*
                   1149:         *      Only one pageability change may take place at one
                   1150:         *      time, since vm_fault assumes it will be called
                   1151:         *      only once for each wiring/unwiring.  Therefore, we
                   1152:         *      have to make sure we're actually changing the pageability
                   1153:         *      for the entire region.  We do so before making any changes.
                   1154:         */
                   1155: 
                   1156:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1157:                entry = temp_entry;
                   1158:                vm_map_clip_start(map, entry, start);
                   1159:        }
                   1160:        else
                   1161:                entry = temp_entry->next;
                   1162:        temp_entry = entry;
                   1163: 
                   1164:        /*
                   1165:         *      Actions are rather different for wiring and unwiring,
                   1166:         *      so we have two separate cases.
                   1167:         */
                   1168: 
                   1169:        if (new_pageable) {
                   1170: 
                   1171:                /*
                   1172:                 *      Unwiring.  First ensure that the range to be
                   1173:                 *      unwired is really wired down.
                   1174:                 */
                   1175:                while ((entry != &map->header) && (entry->start < end)) {
                   1176: 
                   1177:                    if (entry->wired_count == 0) {
                   1178:                        vm_map_unlock(map);
                   1179:                        return(KERN_INVALID_ARGUMENT);
                   1180:                    }
                   1181:                    entry = entry->next;
                   1182:                }
                   1183: 
                   1184:                /*
                   1185:                 *      Now decrement the wiring count for each region.
                   1186:                 *      If a region becomes completely unwired,
                   1187:                 *      unwire its physical pages and mappings.
                   1188:                 */
                   1189:                lock_set_recursive(&map->lock);
                   1190: 
                   1191:                entry = temp_entry;
                   1192:                while ((entry != &map->header) && (entry->start < end)) {
                   1193:                    vm_map_clip_end(map, entry, end);
                   1194: 
                   1195:                    entry->wired_count--;
                   1196:                    if (entry->wired_count == 0)
                   1197:                        vm_fault_unwire(map, entry->start, entry->end);
                   1198: 
                   1199:                    entry = entry->next;
                   1200:                }
                   1201:                lock_clear_recursive(&map->lock);
                   1202:        }
                   1203: 
                   1204:        else {
                   1205:                /*
                   1206:                 *      Wiring.  We must do this in two passes:
                   1207:                 *
                   1208:                 *      1.  Holding the write lock, we increment the
                   1209:                 *          wiring count.  For any area that is not already
                   1210:                 *          wired, we create any shadow objects that need
                   1211:                 *          to be created.
                   1212:                 *
                   1213:                 *      2.  We downgrade to a read lock, and call
                   1214:                 *          vm_fault_wire to fault in the pages for any
                   1215:                 *          newly wired area (wired_count is 1).
                   1216:                 *
                   1217:                 *      Downgrading to a read lock for vm_fault_wire avoids
                   1218:                 *      a possible deadlock with another thread that may have
                   1219:                 *      faulted on one of the pages to be wired (it would mark
                   1220:                 *      the page busy, blocking us, then in turn block on the
                   1221:                 *      map lock that we hold).  Because of problems in the
                   1222:                 *      recursive lock package, we cannot upgrade to a write
                   1223:                 *      lock in vm_map_lookup.  Thus, any actions that require
                   1224:                 *      the write lock must be done beforehand.  Because we
                   1225:                 *      keep the read lock on the map, the copy-on-write status
                   1226:                 *      of the entries we modify here cannot change.
                   1227:                 */
                   1228: 
                   1229:                /*
                   1230:                 *      Pass 1.
                   1231:                 */
                   1232:                entry = temp_entry;
                   1233:                while ((entry != &map->header) && (entry->start < end)) {
                   1234:                    vm_map_clip_end(map, entry, end);
                   1235: 
                   1236:                    entry->wired_count++;
                   1237:                    if (entry->wired_count == 1) {
                   1238: 
                   1239:                        /*
                   1240:                         *      Perform actions of vm_map_lookup that need
                   1241:                         *      the write lock on the map: create a shadow
                   1242:                         *      object for a copy-on-write region, or an
                   1243:                         *      object for a zero-fill region.
                   1244:                         *
                   1245:                         *      We don't have to do this for entries that
                   1246:                         *      point to sharing maps, because we won't hold
                   1247:                         *      the lock on the sharing map.
                   1248:                         */
                   1249:                        if (!entry->is_a_map) {
                   1250:                            if (entry->needs_copy &&
                   1251:                                ((entry->protection & VM_PROT_WRITE) != 0)) {
                   1252: 
                   1253:                                vm_object_shadow(&entry->object.vm_object,
                   1254:                                                &entry->offset,
                   1255:                                                (vm_size_t)(entry->end
                   1256:                                                        - entry->start));
                   1257:                                entry->needs_copy = FALSE;
                   1258:                            }
                   1259:                            else if (entry->object.vm_object == NULL) {
                   1260:                                entry->object.vm_object =
                   1261:                                    vm_object_allocate((vm_size_t)(entry->end
                   1262:                                                        - entry->start));
                   1263:                                entry->offset = (vm_offset_t)0;
                   1264:                            }
                   1265:                        }
                   1266:                    }
                   1267: 
                   1268:                    entry = entry->next;
                   1269:                }
                   1270: 
                   1271:                /*
                   1272:                 *      Pass 2.
                   1273:                 */
                   1274: 
                   1275:                /*
                   1276:                 * HACK HACK HACK HACK
                   1277:                 *
                   1278:                 * If we are wiring in the kernel map or a submap of it,
                   1279:                 * unlock the map to avoid deadlocks.  We trust that the
                   1280:                 * kernel threads are well-behaved, and therefore will
                   1281:                 * not do anything destructive to this region of the map
                   1282:                 * while we have it unlocked.  We cannot trust user threads
                   1283:                 * to do the same.
                   1284:                 *
                   1285:                 * HACK HACK HACK HACK
                   1286:                 */
                   1287:                if (vm_map_pmap(map) == kernel_pmap) {
                   1288:                    vm_map_unlock(map);         /* trust me ... */
                   1289:                }
                   1290:                else {
                   1291:                    lock_set_recursive(&map->lock);
                   1292:                    lock_write_to_read(&map->lock);
                   1293:                }
                   1294: 
                   1295:                entry = temp_entry;
                   1296:                while (entry != &map->header && entry->start < end) {
1.1.1.4 ! root     1297:                    if (entry->wired_count == 1) {
        !          1298:                        vm_fault_wire(map, entry->start, entry->end);
1.1       root     1299:                    }
                   1300:                    entry = entry->next;
                   1301:                }
                   1302: 
                   1303:                if (vm_map_pmap(map) == kernel_pmap) {
                   1304:                    vm_map_lock(map);
                   1305:                }
                   1306:                else {
                   1307:                    lock_clear_recursive(&map->lock);
                   1308:                }
                   1309:        }
                   1310: 
                   1311:        vm_map_unlock(map);
                   1312: 
                   1313:        return(KERN_SUCCESS);
                   1314: }
                   1315: 
                   1316: /*
                   1317:  *     vm_map_entry_unwire:    [ internal use only ]
                   1318:  *
                   1319:  *     Make the region specified by this entry pageable.
                   1320:  *
                   1321:  *     The map in question should be locked.
                   1322:  *     [This is the reason for this routine's existence.]
                   1323:  */
1.1.1.4 ! root     1324: void
        !          1325: vm_map_entry_unwire(map, entry)
1.1       root     1326:        vm_map_t                map;
                   1327:        register vm_map_entry_t entry;
                   1328: {
                   1329:        vm_fault_unwire(map, entry->start, entry->end);
                   1330:        entry->wired_count = 0;
                   1331: }
                   1332: 
                   1333: /*
                   1334:  *     vm_map_entry_delete:    [ internal use only ]
                   1335:  *
                   1336:  *     Deallocate the given entry from the target map.
                   1337:  */            
1.1.1.4 ! root     1338: void
        !          1339: vm_map_entry_delete(map, entry)
1.1       root     1340:        register vm_map_t       map;
                   1341:        register vm_map_entry_t entry;
                   1342: {
                   1343:        if (entry->wired_count != 0)
                   1344:                vm_map_entry_unwire(map, entry);
                   1345:                
                   1346:        vm_map_entry_unlink(map, entry);
                   1347:        map->size -= entry->end - entry->start;
                   1348: 
                   1349:        if (entry->is_a_map || entry->is_sub_map)
                   1350:                vm_map_deallocate(entry->object.share_map);
                   1351:        else
                   1352:                vm_object_deallocate(entry->object.vm_object);
                   1353: 
                   1354:        vm_map_entry_dispose(map, entry);
                   1355: }
                   1356: 
                   1357: /*
                   1358:  *     vm_map_delete:  [ internal use only ]
                   1359:  *
                   1360:  *     Deallocates the given address range from the target
                   1361:  *     map.
                   1362:  *
                   1363:  *     When called with a sharing map, removes pages from
                   1364:  *     that region from all physical maps.
                   1365:  */
1.1.1.4 ! root     1366: int
1.1       root     1367: vm_map_delete(map, start, end)
                   1368:        register vm_map_t       map;
                   1369:        vm_offset_t             start;
                   1370:        register vm_offset_t    end;
                   1371: {
                   1372:        register vm_map_entry_t entry;
                   1373:        vm_map_entry_t          first_entry;
                   1374: 
                   1375:        /*
                   1376:         *      Find the start of the region, and clip it
                   1377:         */
                   1378: 
                   1379:        if (!vm_map_lookup_entry(map, start, &first_entry))
                   1380:                entry = first_entry->next;
                   1381:        else {
                   1382:                entry = first_entry;
                   1383:                vm_map_clip_start(map, entry, start);
                   1384: 
                   1385:                /*
                   1386:                 *      Fix the lookup hint now, rather than each
                   1387:                 *      time though the loop.
                   1388:                 */
                   1389: 
                   1390:                SAVE_HINT(map, entry->prev);
                   1391:        }
                   1392: 
                   1393:        /*
                   1394:         *      Save the free space hint
                   1395:         */
                   1396: 
                   1397:        if (map->first_free->start >= start)
                   1398:                map->first_free = entry->prev;
                   1399: 
                   1400:        /*
                   1401:         *      Step through all entries in this region
                   1402:         */
                   1403: 
                   1404:        while ((entry != &map->header) && (entry->start < end)) {
                   1405:                vm_map_entry_t          next;
                   1406:                register vm_offset_t    s, e;
                   1407:                register vm_object_t    object;
                   1408: 
                   1409:                vm_map_clip_end(map, entry, end);
                   1410: 
                   1411:                next = entry->next;
                   1412:                s = entry->start;
                   1413:                e = entry->end;
                   1414: 
                   1415:                /*
                   1416:                 *      Unwire before removing addresses from the pmap;
                   1417:                 *      otherwise, unwiring will put the entries back in
                   1418:                 *      the pmap.
                   1419:                 */
                   1420: 
                   1421:                object = entry->object.vm_object;
                   1422:                if (entry->wired_count != 0)
                   1423:                        vm_map_entry_unwire(map, entry);
                   1424: 
                   1425:                /*
                   1426:                 *      If this is a sharing map, we must remove
                   1427:                 *      *all* references to this data, since we can't
                   1428:                 *      find all of the physical maps which are sharing
                   1429:                 *      it.
                   1430:                 */
                   1431: 
                   1432:                if (object == kernel_object || object == kmem_object)
                   1433:                        vm_object_page_remove(object, entry->offset,
                   1434:                                        entry->offset + (e - s));
                   1435:                else if (!map->is_main_map)
                   1436:                        vm_object_pmap_remove(object,
                   1437:                                         entry->offset,
                   1438:                                         entry->offset + (e - s));
                   1439:                else
                   1440:                        pmap_remove(map->pmap, s, e);
                   1441: 
                   1442:                /*
                   1443:                 *      Delete the entry (which may delete the object)
                   1444:                 *      only after removing all pmap entries pointing
                   1445:                 *      to its pages.  (Otherwise, its page frames may
                   1446:                 *      be reallocated, and any modify bits will be
                   1447:                 *      set in the wrong object!)
                   1448:                 */
                   1449: 
                   1450:                vm_map_entry_delete(map, entry);
                   1451:                entry = next;
                   1452:        }
                   1453:        return(KERN_SUCCESS);
                   1454: }
                   1455: 
                   1456: /*
                   1457:  *     vm_map_remove:
                   1458:  *
                   1459:  *     Remove the given address range from the target map.
                   1460:  *     This is the exported form of vm_map_delete.
                   1461:  */
1.1.1.4 ! root     1462: int
1.1       root     1463: vm_map_remove(map, start, end)
                   1464:        register vm_map_t       map;
                   1465:        register vm_offset_t    start;
                   1466:        register vm_offset_t    end;
                   1467: {
                   1468:        register int            result;
                   1469: 
                   1470:        vm_map_lock(map);
                   1471:        VM_MAP_RANGE_CHECK(map, start, end);
                   1472:        result = vm_map_delete(map, start, end);
                   1473:        vm_map_unlock(map);
                   1474: 
                   1475:        return(result);
                   1476: }
                   1477: 
                   1478: /*
                   1479:  *     vm_map_check_protection:
                   1480:  *
                   1481:  *     Assert that the target map allows the specified
                   1482:  *     privilege on the entire address region given.
                   1483:  *     The entire region must be allocated.
                   1484:  */
                   1485: boolean_t vm_map_check_protection(map, start, end, protection)
                   1486:        register vm_map_t       map;
                   1487:        register vm_offset_t    start;
                   1488:        register vm_offset_t    end;
                   1489:        register vm_prot_t      protection;
                   1490: {
                   1491:        register vm_map_entry_t entry;
                   1492:        vm_map_entry_t          tmp_entry;
                   1493: 
                   1494:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   1495:                return(FALSE);
                   1496:        }
                   1497: 
                   1498:        entry = tmp_entry;
                   1499: 
                   1500:        while (start < end) {
                   1501:                if (entry == &map->header) {
                   1502:                        return(FALSE);
                   1503:                }
                   1504: 
                   1505:                /*
                   1506:                 *      No holes allowed!
                   1507:                 */
                   1508: 
                   1509:                if (start < entry->start) {
                   1510:                        return(FALSE);
                   1511:                }
                   1512: 
                   1513:                /*
                   1514:                 * Check protection associated with entry.
                   1515:                 */
                   1516: 
                   1517:                if ((entry->protection & protection) != protection) {
                   1518:                        return(FALSE);
                   1519:                }
                   1520: 
                   1521:                /* go to next entry */
                   1522: 
                   1523:                start = entry->end;
                   1524:                entry = entry->next;
                   1525:        }
                   1526:        return(TRUE);
                   1527: }
                   1528: 
                   1529: /*
                   1530:  *     vm_map_copy_entry:
                   1531:  *
                   1532:  *     Copies the contents of the source entry to the destination
                   1533:  *     entry.  The entries *must* be aligned properly.
                   1534:  */
1.1.1.4 ! root     1535: void
        !          1536: vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
1.1       root     1537:        vm_map_t                src_map, dst_map;
                   1538:        register vm_map_entry_t src_entry, dst_entry;
                   1539: {
                   1540:        vm_object_t     temp_object;
                   1541: 
                   1542:        if (src_entry->is_sub_map || dst_entry->is_sub_map)
                   1543:                return;
                   1544: 
                   1545:        if (dst_entry->object.vm_object != NULL &&
                   1546:            !dst_entry->object.vm_object->internal)
                   1547:                printf("vm_map_copy_entry: copying over permanent data!\n");
                   1548: 
                   1549:        /*
                   1550:         *      If our destination map was wired down,
                   1551:         *      unwire it now.
                   1552:         */
                   1553: 
                   1554:        if (dst_entry->wired_count != 0)
                   1555:                vm_map_entry_unwire(dst_map, dst_entry);
                   1556: 
                   1557:        /*
                   1558:         *      If we're dealing with a sharing map, we
                   1559:         *      must remove the destination pages from
                   1560:         *      all maps (since we cannot know which maps
                   1561:         *      this sharing map belongs in).
                   1562:         */
                   1563: 
                   1564:        if (dst_map->is_main_map)
                   1565:                pmap_remove(dst_map->pmap, dst_entry->start, dst_entry->end);
                   1566:        else
                   1567:                vm_object_pmap_remove(dst_entry->object.vm_object,
                   1568:                        dst_entry->offset,
                   1569:                        dst_entry->offset +
                   1570:                                (dst_entry->end - dst_entry->start));
                   1571: 
                   1572:        if (src_entry->wired_count == 0) {
                   1573: 
                   1574:                boolean_t       src_needs_copy;
                   1575: 
                   1576:                /*
                   1577:                 *      If the source entry is marked needs_copy,
                   1578:                 *      it is already write-protected.
                   1579:                 */
                   1580:                if (!src_entry->needs_copy) {
                   1581: 
                   1582:                        boolean_t       su;
                   1583: 
                   1584:                        /*
                   1585:                         *      If the source entry has only one mapping,
                   1586:                         *      we can just protect the virtual address
                   1587:                         *      range.
                   1588:                         */
                   1589:                        if (!(su = src_map->is_main_map)) {
                   1590:                                simple_lock(&src_map->ref_lock);
                   1591:                                su = (src_map->ref_count == 1);
                   1592:                                simple_unlock(&src_map->ref_lock);
                   1593:                        }
                   1594: 
                   1595:                        if (su) {
                   1596:                                pmap_protect(src_map->pmap,
                   1597:                                        src_entry->start,
                   1598:                                        src_entry->end,
                   1599:                                        src_entry->protection & ~VM_PROT_WRITE);
                   1600:                        }
                   1601:                        else {
                   1602:                                vm_object_pmap_copy(src_entry->object.vm_object,
                   1603:                                        src_entry->offset,
                   1604:                                        src_entry->offset + (src_entry->end
                   1605:                                                            -src_entry->start));
                   1606:                        }
                   1607:                }
                   1608: 
                   1609:                /*
                   1610:                 *      Make a copy of the object.
                   1611:                 */
                   1612:                temp_object = dst_entry->object.vm_object;
                   1613:                vm_object_copy(src_entry->object.vm_object,
                   1614:                                src_entry->offset,
                   1615:                                (vm_size_t)(src_entry->end -
                   1616:                                            src_entry->start),
                   1617:                                &dst_entry->object.vm_object,
                   1618:                                &dst_entry->offset,
                   1619:                                &src_needs_copy);
                   1620:                /*
                   1621:                 *      If we didn't get a copy-object now, mark the
                   1622:                 *      source map entry so that a shadow will be created
                   1623:                 *      to hold its changed pages.
                   1624:                 */
                   1625:                if (src_needs_copy)
                   1626:                        src_entry->needs_copy = TRUE;
                   1627: 
                   1628:                /*
                   1629:                 *      The destination always needs to have a shadow
                   1630:                 *      created.
                   1631:                 */
                   1632:                dst_entry->needs_copy = TRUE;
                   1633: 
                   1634:                /*
                   1635:                 *      Mark the entries copy-on-write, so that write-enabling
                   1636:                 *      the entry won't make copy-on-write pages writable.
                   1637:                 */
                   1638:                src_entry->copy_on_write = TRUE;
                   1639:                dst_entry->copy_on_write = TRUE;
                   1640:                /*
                   1641:                 *      Get rid of the old object.
                   1642:                 */
                   1643:                vm_object_deallocate(temp_object);
                   1644: 
                   1645:                pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start,
                   1646:                        dst_entry->end - dst_entry->start, src_entry->start);
                   1647:        }
                   1648:        else {
                   1649:                /*
                   1650:                 *      Of course, wired down pages can't be set copy-on-write.
                   1651:                 *      Cause wired pages to be copied into the new
                   1652:                 *      map by simulating faults (the new pages are
                   1653:                 *      pageable)
                   1654:                 */
                   1655:                vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
                   1656:        }
                   1657: }
                   1658: 
                   1659: /*
                   1660:  *     vm_map_copy:
                   1661:  *
                   1662:  *     Perform a virtual memory copy from the source
                   1663:  *     address map/range to the destination map/range.
                   1664:  *
                   1665:  *     If src_destroy or dst_alloc is requested,
                   1666:  *     the source and destination regions should be
                   1667:  *     disjoint, not only in the top-level map, but
                   1668:  *     in the sharing maps as well.  [The best way
                   1669:  *     to guarantee this is to use a new intermediate
                   1670:  *     map to make copies.  This also reduces map
                   1671:  *     fragmentation.]
                   1672:  */
1.1.1.4 ! root     1673: int
1.1       root     1674: vm_map_copy(dst_map, src_map,
                   1675:                          dst_addr, len, src_addr,
                   1676:                          dst_alloc, src_destroy)
                   1677:        vm_map_t        dst_map;
                   1678:        vm_map_t        src_map;
                   1679:        vm_offset_t     dst_addr;
                   1680:        vm_size_t       len;
                   1681:        vm_offset_t     src_addr;
                   1682:        boolean_t       dst_alloc;
                   1683:        boolean_t       src_destroy;
                   1684: {
                   1685:        register
                   1686:        vm_map_entry_t  src_entry;
                   1687:        register
                   1688:        vm_map_entry_t  dst_entry;
                   1689:        vm_map_entry_t  tmp_entry;
                   1690:        vm_offset_t     src_start;
                   1691:        vm_offset_t     src_end;
                   1692:        vm_offset_t     dst_start;
                   1693:        vm_offset_t     dst_end;
                   1694:        vm_offset_t     src_clip;
                   1695:        vm_offset_t     dst_clip;
                   1696:        int             result;
                   1697:        boolean_t       old_src_destroy;
                   1698: 
                   1699:        /*
                   1700:         *      XXX While we figure out why src_destroy screws up,
                   1701:         *      we'll do it by explicitly vm_map_delete'ing at the end.
                   1702:         */
                   1703: 
                   1704:        old_src_destroy = src_destroy;
                   1705:        src_destroy = FALSE;
                   1706: 
                   1707:        /*
                   1708:         *      Compute start and end of region in both maps
                   1709:         */
                   1710: 
                   1711:        src_start = src_addr;
                   1712:        src_end = src_start + len;
                   1713:        dst_start = dst_addr;
                   1714:        dst_end = dst_start + len;
                   1715: 
                   1716:        /*
                   1717:         *      Check that the region can exist in both source
                   1718:         *      and destination.
                   1719:         */
                   1720: 
                   1721:        if ((dst_end < dst_start) || (src_end < src_start))
                   1722:                return(KERN_NO_SPACE);
                   1723: 
                   1724:        /*
                   1725:         *      Lock the maps in question -- we avoid deadlock
                   1726:         *      by ordering lock acquisition by map value
                   1727:         */
                   1728: 
                   1729:        if (src_map == dst_map) {
                   1730:                vm_map_lock(src_map);
                   1731:        }
                   1732:        else if ((int) src_map < (int) dst_map) {
                   1733:                vm_map_lock(src_map);
                   1734:                vm_map_lock(dst_map);
                   1735:        } else {
                   1736:                vm_map_lock(dst_map);
                   1737:                vm_map_lock(src_map);
                   1738:        }
                   1739: 
                   1740:        result = KERN_SUCCESS;
                   1741: 
                   1742:        /*
                   1743:         *      Check protections... source must be completely readable and
                   1744:         *      destination must be completely writable.  [Note that if we're
                   1745:         *      allocating the destination region, we don't have to worry
                   1746:         *      about protection, but instead about whether the region
                   1747:         *      exists.]
                   1748:         */
                   1749: 
                   1750:        if (src_map->is_main_map && dst_map->is_main_map) {
                   1751:                if (!vm_map_check_protection(src_map, src_start, src_end,
                   1752:                                        VM_PROT_READ)) {
                   1753:                        result = KERN_PROTECTION_FAILURE;
                   1754:                        goto Return;
                   1755:                }
                   1756: 
                   1757:                if (dst_alloc) {
                   1758:                        /* XXX Consider making this a vm_map_find instead */
                   1759:                        if ((result = vm_map_insert(dst_map, NULL,
                   1760:                                        (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS)
                   1761:                                goto Return;
                   1762:                }
                   1763:                else if (!vm_map_check_protection(dst_map, dst_start, dst_end,
                   1764:                                        VM_PROT_WRITE)) {
                   1765:                        result = KERN_PROTECTION_FAILURE;
                   1766:                        goto Return;
                   1767:                }
                   1768:        }
                   1769: 
                   1770:        /*
                   1771:         *      Find the start entries and clip.
                   1772:         *
                   1773:         *      Note that checking protection asserts that the
                   1774:         *      lookup cannot fail.
                   1775:         *
                   1776:         *      Also note that we wait to do the second lookup
                   1777:         *      until we have done the first clip, as the clip
                   1778:         *      may affect which entry we get!
                   1779:         */
                   1780: 
                   1781:        (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1782:        src_entry = tmp_entry;
                   1783:        vm_map_clip_start(src_map, src_entry, src_start);
                   1784: 
                   1785:        (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry);
                   1786:        dst_entry = tmp_entry;
                   1787:        vm_map_clip_start(dst_map, dst_entry, dst_start);
                   1788: 
                   1789:        /*
                   1790:         *      If both source and destination entries are the same,
                   1791:         *      retry the first lookup, as it may have changed.
                   1792:         */
                   1793: 
                   1794:        if (src_entry == dst_entry) {
                   1795:                (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1796:                src_entry = tmp_entry;
                   1797:        }
                   1798: 
                   1799:        /*
                   1800:         *      If source and destination entries are still the same,
                   1801:         *      a null copy is being performed.
                   1802:         */
                   1803: 
                   1804:        if (src_entry == dst_entry)
                   1805:                goto Return;
                   1806: 
                   1807:        /*
                   1808:         *      Go through entries until we get to the end of the
                   1809:         *      region.
                   1810:         */
                   1811: 
                   1812:        while (src_start < src_end) {
                   1813:                /*
                   1814:                 *      Clip the entries to the endpoint of the entire region.
                   1815:                 */
                   1816: 
                   1817:                vm_map_clip_end(src_map, src_entry, src_end);
                   1818:                vm_map_clip_end(dst_map, dst_entry, dst_end);
                   1819: 
                   1820:                /*
                   1821:                 *      Clip each entry to the endpoint of the other entry.
                   1822:                 */
                   1823: 
                   1824:                src_clip = src_entry->start + (dst_entry->end - dst_entry->start);
                   1825:                vm_map_clip_end(src_map, src_entry, src_clip);
                   1826: 
                   1827:                dst_clip = dst_entry->start + (src_entry->end - src_entry->start);
                   1828:                vm_map_clip_end(dst_map, dst_entry, dst_clip);
                   1829: 
                   1830:                /*
                   1831:                 *      Both entries now match in size and relative endpoints.
                   1832:                 *
                   1833:                 *      If both entries refer to a VM object, we can
                   1834:                 *      deal with them now.
                   1835:                 */
                   1836: 
                   1837:                if (!src_entry->is_a_map && !dst_entry->is_a_map) {
                   1838:                        vm_map_copy_entry(src_map, dst_map, src_entry,
                   1839:                                                dst_entry);
                   1840:                }
                   1841:                else {
                   1842:                        register vm_map_t       new_dst_map;
                   1843:                        vm_offset_t             new_dst_start;
                   1844:                        vm_size_t               new_size;
                   1845:                        vm_map_t                new_src_map;
                   1846:                        vm_offset_t             new_src_start;
                   1847: 
                   1848:                        /*
                   1849:                         *      We have to follow at least one sharing map.
                   1850:                         */
                   1851: 
                   1852:                        new_size = (dst_entry->end - dst_entry->start);
                   1853: 
                   1854:                        if (src_entry->is_a_map) {
                   1855:                                new_src_map = src_entry->object.share_map;
                   1856:                                new_src_start = src_entry->offset;
                   1857:                        }
                   1858:                        else {
                   1859:                                new_src_map = src_map;
                   1860:                                new_src_start = src_entry->start;
                   1861:                                lock_set_recursive(&src_map->lock);
                   1862:                        }
                   1863: 
                   1864:                        if (dst_entry->is_a_map) {
                   1865:                                vm_offset_t     new_dst_end;
                   1866: 
                   1867:                                new_dst_map = dst_entry->object.share_map;
                   1868:                                new_dst_start = dst_entry->offset;
                   1869: 
                   1870:                                /*
                   1871:                                 *      Since the destination sharing entries
                   1872:                                 *      will be merely deallocated, we can
                   1873:                                 *      do that now, and replace the region
                   1874:                                 *      with a null object.  [This prevents
                   1875:                                 *      splitting the source map to match
                   1876:                                 *      the form of the destination map.]
                   1877:                                 *      Note that we can only do so if the
                   1878:                                 *      source and destination do not overlap.
                   1879:                                 */
                   1880: 
                   1881:                                new_dst_end = new_dst_start + new_size;
                   1882: 
                   1883:                                if (new_dst_map != new_src_map) {
                   1884:                                        vm_map_lock(new_dst_map);
                   1885:                                        (void) vm_map_delete(new_dst_map,
                   1886:                                                        new_dst_start,
                   1887:                                                        new_dst_end);
                   1888:                                        (void) vm_map_insert(new_dst_map,
                   1889:                                                        NULL,
                   1890:                                                        (vm_offset_t) 0,
                   1891:                                                        new_dst_start,
                   1892:                                                        new_dst_end);
                   1893:                                        vm_map_unlock(new_dst_map);
                   1894:                                }
                   1895:                        }
                   1896:                        else {
                   1897:                                new_dst_map = dst_map;
                   1898:                                new_dst_start = dst_entry->start;
                   1899:                                lock_set_recursive(&dst_map->lock);
                   1900:                        }
                   1901: 
                   1902:                        /*
                   1903:                         *      Recursively copy the sharing map.
                   1904:                         */
                   1905: 
                   1906:                        (void) vm_map_copy(new_dst_map, new_src_map,
                   1907:                                new_dst_start, new_size, new_src_start,
                   1908:                                FALSE, FALSE);
                   1909: 
                   1910:                        if (dst_map == new_dst_map)
                   1911:                                lock_clear_recursive(&dst_map->lock);
                   1912:                        if (src_map == new_src_map)
                   1913:                                lock_clear_recursive(&src_map->lock);
                   1914:                }
                   1915: 
                   1916:                /*
                   1917:                 *      Update variables for next pass through the loop.
                   1918:                 */
                   1919: 
                   1920:                src_start = src_entry->end;
                   1921:                src_entry = src_entry->next;
                   1922:                dst_start = dst_entry->end;
                   1923:                dst_entry = dst_entry->next;
                   1924: 
                   1925:                /*
                   1926:                 *      If the source is to be destroyed, here is the
                   1927:                 *      place to do it.
                   1928:                 */
                   1929: 
                   1930:                if (src_destroy && src_map->is_main_map &&
                   1931:                                                dst_map->is_main_map)
                   1932:                        vm_map_entry_delete(src_map, src_entry->prev);
                   1933:        }
                   1934: 
                   1935:        /*
                   1936:         *      Update the physical maps as appropriate
                   1937:         */
                   1938: 
                   1939:        if (src_map->is_main_map && dst_map->is_main_map) {
                   1940:                if (src_destroy)
                   1941:                        pmap_remove(src_map->pmap, src_addr, src_addr + len);
                   1942:        }
                   1943: 
                   1944:        /*
                   1945:         *      Unlock the maps
                   1946:         */
                   1947: 
                   1948:        Return: ;
                   1949: 
                   1950:        if (old_src_destroy)
                   1951:                vm_map_delete(src_map, src_addr, src_addr + len);
                   1952: 
                   1953:        vm_map_unlock(src_map);
                   1954:        if (src_map != dst_map)
                   1955:                vm_map_unlock(dst_map);
                   1956: 
                   1957:        return(result);
                   1958: }
                   1959: 
                   1960: /*
                   1961:  * vmspace_fork:
                   1962:  * Create a new process vmspace structure and vm_map
                   1963:  * based on those of an existing process.  The new map
                   1964:  * is based on the old map, according to the inheritance
                   1965:  * values on the regions in that map.
                   1966:  *
                   1967:  * The source map must not be locked.
                   1968:  */
                   1969: struct vmspace *
                   1970: vmspace_fork(vm1)
                   1971:        register struct vmspace *vm1;
                   1972: {
                   1973:        register struct vmspace *vm2;
                   1974:        vm_map_t        old_map = &vm1->vm_map;
                   1975:        vm_map_t        new_map;
                   1976:        vm_map_entry_t  old_entry;
                   1977:        vm_map_entry_t  new_entry;
                   1978:        pmap_t          new_pmap;
                   1979: 
                   1980:        vm_map_lock(old_map);
                   1981: 
                   1982:        vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset,
                   1983:            old_map->entries_pageable);
                   1984:        bcopy(&vm1->vm_startcopy, &vm2->vm_startcopy,
                   1985:            (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy);
                   1986:        new_pmap = &vm2->vm_pmap;               /* XXX */
                   1987:        new_map = &vm2->vm_map;                 /* XXX */
                   1988: 
                   1989:        old_entry = old_map->header.next;
                   1990: 
                   1991:        while (old_entry != &old_map->header) {
                   1992:                if (old_entry->is_sub_map)
                   1993:                        panic("vm_map_fork: encountered a submap");
                   1994: 
                   1995:                switch (old_entry->inheritance) {
                   1996:                case VM_INHERIT_NONE:
                   1997:                        break;
                   1998: 
                   1999:                case VM_INHERIT_SHARE:
                   2000:                        /*
                   2001:                         *      If we don't already have a sharing map:
                   2002:                         */
                   2003: 
                   2004:                        if (!old_entry->is_a_map) {
                   2005:                                vm_map_t        new_share_map;
                   2006:                                vm_map_entry_t  new_share_entry;
                   2007:                                
                   2008:                                /*
                   2009:                                 *      Create a new sharing map
                   2010:                                 */
                   2011:                                 
                   2012:                                new_share_map = vm_map_create(NULL,
                   2013:                                                        old_entry->start,
                   2014:                                                        old_entry->end,
                   2015:                                                        TRUE);
                   2016:                                new_share_map->is_main_map = FALSE;
                   2017: 
                   2018:                                /*
                   2019:                                 *      Create the only sharing entry from the
                   2020:                                 *      old task map entry.
                   2021:                                 */
                   2022: 
                   2023:                                new_share_entry =
                   2024:                                        vm_map_entry_create(new_share_map);
                   2025:                                *new_share_entry = *old_entry;
                   2026: 
                   2027:                                /*
                   2028:                                 *      Insert the entry into the new sharing
                   2029:                                 *      map
                   2030:                                 */
                   2031: 
                   2032:                                vm_map_entry_link(new_share_map,
                   2033:                                                new_share_map->header.prev,
                   2034:                                                new_share_entry);
                   2035: 
                   2036:                                /*
                   2037:                                 *      Fix up the task map entry to refer
                   2038:                                 *      to the sharing map now.
                   2039:                                 */
                   2040: 
                   2041:                                old_entry->is_a_map = TRUE;
                   2042:                                old_entry->object.share_map = new_share_map;
                   2043:                                old_entry->offset = old_entry->start;
                   2044:                        }
                   2045: 
                   2046:                        /*
                   2047:                         *      Clone the entry, referencing the sharing map.
                   2048:                         */
                   2049: 
                   2050:                        new_entry = vm_map_entry_create(new_map);
                   2051:                        *new_entry = *old_entry;
                   2052:                        vm_map_reference(new_entry->object.share_map);
                   2053: 
                   2054:                        /*
                   2055:                         *      Insert the entry into the new map -- we
                   2056:                         *      know we're inserting at the end of the new
                   2057:                         *      map.
                   2058:                         */
                   2059: 
                   2060:                        vm_map_entry_link(new_map, new_map->header.prev,
                   2061:                                                new_entry);
                   2062: 
                   2063:                        /*
                   2064:                         *      Update the physical map
                   2065:                         */
                   2066: 
                   2067:                        pmap_copy(new_map->pmap, old_map->pmap,
                   2068:                                new_entry->start,
                   2069:                                (old_entry->end - old_entry->start),
                   2070:                                old_entry->start);
                   2071:                        break;
                   2072: 
                   2073:                case VM_INHERIT_COPY:
                   2074:                        /*
                   2075:                         *      Clone the entry and link into the map.
                   2076:                         */
                   2077: 
                   2078:                        new_entry = vm_map_entry_create(new_map);
                   2079:                        *new_entry = *old_entry;
                   2080:                        new_entry->wired_count = 0;
                   2081:                        new_entry->object.vm_object = NULL;
                   2082:                        new_entry->is_a_map = FALSE;
                   2083:                        vm_map_entry_link(new_map, new_map->header.prev,
                   2084:                                                        new_entry);
                   2085:                        if (old_entry->is_a_map) {
                   2086:                                int     check;
                   2087: 
                   2088:                                check = vm_map_copy(new_map,
                   2089:                                                old_entry->object.share_map,
                   2090:                                                new_entry->start,
                   2091:                                                (vm_size_t)(new_entry->end -
                   2092:                                                        new_entry->start),
                   2093:                                                old_entry->offset,
                   2094:                                                FALSE, FALSE);
                   2095:                                if (check != KERN_SUCCESS)
                   2096:                                        printf("vm_map_fork: copy in share_map region failed\n");
                   2097:                        }
                   2098:                        else {
                   2099:                                vm_map_copy_entry(old_map, new_map, old_entry,
                   2100:                                                new_entry);
                   2101:                        }
                   2102:                        break;
                   2103:                }
                   2104:                old_entry = old_entry->next;
                   2105:        }
                   2106: 
                   2107:        new_map->size = old_map->size;
                   2108:        vm_map_unlock(old_map);
                   2109: 
                   2110:        return(vm2);
                   2111: }
                   2112: 
                   2113: /*
                   2114:  *     vm_map_lookup:
                   2115:  *
                   2116:  *     Finds the VM object, offset, and
                   2117:  *     protection for a given virtual address in the
                   2118:  *     specified map, assuming a page fault of the
                   2119:  *     type specified.
                   2120:  *
                   2121:  *     Leaves the map in question locked for read; return
                   2122:  *     values are guaranteed until a vm_map_lookup_done
                   2123:  *     call is performed.  Note that the map argument
                   2124:  *     is in/out; the returned map must be used in
                   2125:  *     the call to vm_map_lookup_done.
                   2126:  *
                   2127:  *     A handle (out_entry) is returned for use in
                   2128:  *     vm_map_lookup_done, to make that fast.
                   2129:  *
                   2130:  *     If a lookup is requested with "write protection"
                   2131:  *     specified, the map may be changed to perform virtual
                   2132:  *     copying operations, although the data referenced will
                   2133:  *     remain the same.
                   2134:  */
                   2135: vm_map_lookup(var_map, vaddr, fault_type, out_entry,
                   2136:                                object, offset, out_prot, wired, single_use)
                   2137:        vm_map_t                *var_map;       /* IN/OUT */
                   2138:        register vm_offset_t    vaddr;
                   2139:        register vm_prot_t      fault_type;
                   2140: 
                   2141:        vm_map_entry_t          *out_entry;     /* OUT */
                   2142:        vm_object_t             *object;        /* OUT */
                   2143:        vm_offset_t             *offset;        /* OUT */
                   2144:        vm_prot_t               *out_prot;      /* OUT */
                   2145:        boolean_t               *wired;         /* OUT */
                   2146:        boolean_t               *single_use;    /* OUT */
                   2147: {
                   2148:        vm_map_t                        share_map;
                   2149:        vm_offset_t                     share_offset;
                   2150:        register vm_map_entry_t         entry;
                   2151:        register vm_map_t               map = *var_map;
                   2152:        register vm_prot_t              prot;
                   2153:        register boolean_t              su;
                   2154: 
                   2155:        RetryLookup: ;
                   2156: 
                   2157:        /*
                   2158:         *      Lookup the faulting address.
                   2159:         */
                   2160: 
                   2161:        vm_map_lock_read(map);
                   2162: 
                   2163: #define        RETURN(why) \
                   2164:                { \
                   2165:                vm_map_unlock_read(map); \
                   2166:                return(why); \
                   2167:                }
                   2168: 
                   2169:        /*
                   2170:         *      If the map has an interesting hint, try it before calling
                   2171:         *      full blown lookup routine.
                   2172:         */
                   2173: 
                   2174:        simple_lock(&map->hint_lock);
                   2175:        entry = map->hint;
                   2176:        simple_unlock(&map->hint_lock);
                   2177: 
                   2178:        *out_entry = entry;
                   2179: 
                   2180:        if ((entry == &map->header) ||
                   2181:            (vaddr < entry->start) || (vaddr >= entry->end)) {
                   2182:                vm_map_entry_t  tmp_entry;
                   2183: 
                   2184:                /*
                   2185:                 *      Entry was either not a valid hint, or the vaddr
                   2186:                 *      was not contained in the entry, so do a full lookup.
                   2187:                 */
                   2188:                if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
                   2189:                        RETURN(KERN_INVALID_ADDRESS);
                   2190: 
                   2191:                entry = tmp_entry;
                   2192:                *out_entry = entry;
                   2193:        }
                   2194: 
                   2195:        /*
                   2196:         *      Handle submaps.
                   2197:         */
                   2198: 
                   2199:        if (entry->is_sub_map) {
                   2200:                vm_map_t        old_map = map;
                   2201: 
                   2202:                *var_map = map = entry->object.sub_map;
                   2203:                vm_map_unlock_read(old_map);
                   2204:                goto RetryLookup;
                   2205:        }
                   2206:                
                   2207:        /*
                   2208:         *      Check whether this task is allowed to have
                   2209:         *      this page.
                   2210:         */
                   2211: 
                   2212:        prot = entry->protection;
                   2213:        if ((fault_type & (prot)) != fault_type)
                   2214:                RETURN(KERN_PROTECTION_FAILURE);
                   2215: 
                   2216:        /*
                   2217:         *      If this page is not pageable, we have to get
                   2218:         *      it for all possible accesses.
                   2219:         */
                   2220: 
                   2221:        if (*wired = (entry->wired_count != 0))
                   2222:                prot = fault_type = entry->protection;
                   2223: 
                   2224:        /*
                   2225:         *      If we don't already have a VM object, track
                   2226:         *      it down.
                   2227:         */
                   2228: 
                   2229:        if (su = !entry->is_a_map) {
                   2230:                share_map = map;
                   2231:                share_offset = vaddr;
                   2232:        }
                   2233:        else {
                   2234:                vm_map_entry_t  share_entry;
                   2235: 
                   2236:                /*
                   2237:                 *      Compute the sharing map, and offset into it.
                   2238:                 */
                   2239: 
                   2240:                share_map = entry->object.share_map;
                   2241:                share_offset = (vaddr - entry->start) + entry->offset;
                   2242: 
                   2243:                /*
                   2244:                 *      Look for the backing store object and offset
                   2245:                 */
                   2246: 
                   2247:                vm_map_lock_read(share_map);
                   2248: 
                   2249:                if (!vm_map_lookup_entry(share_map, share_offset,
                   2250:                                        &share_entry)) {
                   2251:                        vm_map_unlock_read(share_map);
                   2252:                        RETURN(KERN_INVALID_ADDRESS);
                   2253:                }
                   2254:                entry = share_entry;
                   2255:        }
                   2256: 
                   2257:        /*
                   2258:         *      If the entry was copy-on-write, we either ...
                   2259:         */
                   2260: 
                   2261:        if (entry->needs_copy) {
                   2262:                /*
                   2263:                 *      If we want to write the page, we may as well
                   2264:                 *      handle that now since we've got the sharing
                   2265:                 *      map locked.
                   2266:                 *
                   2267:                 *      If we don't need to write the page, we just
                   2268:                 *      demote the permissions allowed.
                   2269:                 */
                   2270: 
                   2271:                if (fault_type & VM_PROT_WRITE) {
                   2272:                        /*
                   2273:                         *      Make a new object, and place it in the
                   2274:                         *      object chain.  Note that no new references
                   2275:                         *      have appeared -- one just moved from the
                   2276:                         *      share map to the new object.
                   2277:                         */
                   2278: 
                   2279:                        if (lock_read_to_write(&share_map->lock)) {
                   2280:                                if (share_map != map)
                   2281:                                        vm_map_unlock_read(map);
                   2282:                                goto RetryLookup;
                   2283:                        }
                   2284: 
                   2285:                        vm_object_shadow(
                   2286:                                &entry->object.vm_object,
                   2287:                                &entry->offset,
                   2288:                                (vm_size_t) (entry->end - entry->start));
                   2289:                                
                   2290:                        entry->needs_copy = FALSE;
                   2291:                        
                   2292:                        lock_write_to_read(&share_map->lock);
                   2293:                }
                   2294:                else {
                   2295:                        /*
                   2296:                         *      We're attempting to read a copy-on-write
                   2297:                         *      page -- don't allow writes.
                   2298:                         */
                   2299: 
                   2300:                        prot &= (~VM_PROT_WRITE);
                   2301:                }
                   2302:        }
                   2303: 
                   2304:        /*
                   2305:         *      Create an object if necessary.
                   2306:         */
                   2307:        if (entry->object.vm_object == NULL) {
                   2308: 
                   2309:                if (lock_read_to_write(&share_map->lock)) {
                   2310:                        if (share_map != map)
                   2311:                                vm_map_unlock_read(map);
                   2312:                        goto RetryLookup;
                   2313:                }
                   2314: 
                   2315:                entry->object.vm_object = vm_object_allocate(
                   2316:                                        (vm_size_t)(entry->end - entry->start));
                   2317:                entry->offset = 0;
                   2318:                lock_write_to_read(&share_map->lock);
                   2319:        }
                   2320: 
                   2321:        /*
                   2322:         *      Return the object/offset from this entry.  If the entry
                   2323:         *      was copy-on-write or empty, it has been fixed up.
                   2324:         */
                   2325: 
                   2326:        *offset = (share_offset - entry->start) + entry->offset;
                   2327:        *object = entry->object.vm_object;
                   2328: 
                   2329:        /*
                   2330:         *      Return whether this is the only map sharing this data.
                   2331:         */
                   2332: 
                   2333:        if (!su) {
                   2334:                simple_lock(&share_map->ref_lock);
                   2335:                su = (share_map->ref_count == 1);
                   2336:                simple_unlock(&share_map->ref_lock);
                   2337:        }
                   2338: 
                   2339:        *out_prot = prot;
                   2340:        *single_use = su;
                   2341: 
                   2342:        return(KERN_SUCCESS);
                   2343:        
                   2344: #undef RETURN
                   2345: }
                   2346: 
                   2347: /*
                   2348:  *     vm_map_lookup_done:
                   2349:  *
                   2350:  *     Releases locks acquired by a vm_map_lookup
                   2351:  *     (according to the handle returned by that lookup).
                   2352:  */
                   2353: 
1.1.1.4 ! root     2354: void
        !          2355: vm_map_lookup_done(map, entry)
1.1       root     2356:        register vm_map_t       map;
                   2357:        vm_map_entry_t          entry;
                   2358: {
                   2359:        /*
                   2360:         *      If this entry references a map, unlock it first.
                   2361:         */
                   2362: 
                   2363:        if (entry->is_a_map)
                   2364:                vm_map_unlock_read(entry->object.share_map);
                   2365: 
                   2366:        /*
                   2367:         *      Unlock the main-level map
                   2368:         */
                   2369: 
                   2370:        vm_map_unlock_read(map);
                   2371: }
                   2372: 
                   2373: /*
                   2374:  *     Routine:        vm_map_simplify
                   2375:  *     Purpose:
                   2376:  *             Attempt to simplify the map representation in
                   2377:  *             the vicinity of the given starting address.
                   2378:  *     Note:
                   2379:  *             This routine is intended primarily to keep the
                   2380:  *             kernel maps more compact -- they generally don't
                   2381:  *             benefit from the "expand a map entry" technology
                   2382:  *             at allocation time because the adjacent entry
                   2383:  *             is often wired down.
                   2384:  */
1.1.1.4 ! root     2385: void
        !          2386: vm_map_simplify(map, start)
1.1       root     2387:        vm_map_t        map;
                   2388:        vm_offset_t     start;
                   2389: {
                   2390:        vm_map_entry_t  this_entry;
                   2391:        vm_map_entry_t  prev_entry;
                   2392: 
                   2393:        vm_map_lock(map);
                   2394:        if (
                   2395:                (vm_map_lookup_entry(map, start, &this_entry)) &&
                   2396:                ((prev_entry = this_entry->prev) != &map->header) &&
                   2397: 
                   2398:                (prev_entry->end == start) &&
                   2399:                (map->is_main_map) &&
                   2400: 
                   2401:                (prev_entry->is_a_map == FALSE) &&
                   2402:                (prev_entry->is_sub_map == FALSE) &&
                   2403: 
                   2404:                (this_entry->is_a_map == FALSE) &&
                   2405:                (this_entry->is_sub_map == FALSE) &&
                   2406: 
                   2407:                (prev_entry->inheritance == this_entry->inheritance) &&
                   2408:                (prev_entry->protection == this_entry->protection) &&
                   2409:                (prev_entry->max_protection == this_entry->max_protection) &&
                   2410:                (prev_entry->wired_count == this_entry->wired_count) &&
                   2411:                
                   2412:                (prev_entry->copy_on_write == this_entry->copy_on_write) &&
                   2413:                (prev_entry->needs_copy == this_entry->needs_copy) &&
                   2414:                
                   2415:                (prev_entry->object.vm_object == this_entry->object.vm_object) &&
                   2416:                ((prev_entry->offset + (prev_entry->end - prev_entry->start))
                   2417:                     == this_entry->offset)
                   2418:        ) {
                   2419:                if (map->first_free == this_entry)
                   2420:                        map->first_free = prev_entry;
                   2421: 
                   2422:                SAVE_HINT(map, prev_entry);
                   2423:                vm_map_entry_unlink(map, this_entry);
                   2424:                prev_entry->end = this_entry->end;
                   2425:                vm_object_deallocate(this_entry->object.vm_object);
                   2426:                vm_map_entry_dispose(map, this_entry);
                   2427:        }
                   2428:        vm_map_unlock(map);
                   2429: }
                   2430: 
                   2431: /*
                   2432:  *     vm_map_print:   [ debug ]
                   2433:  */
1.1.1.4 ! root     2434: void
        !          2435: vm_map_print(map, full)
1.1       root     2436:        register vm_map_t       map;
                   2437:        boolean_t               full;
                   2438: {
                   2439:        register vm_map_entry_t entry;
                   2440:        extern int indent;
                   2441: 
                   2442:        iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
                   2443:                (map->is_main_map ? "Task" : "Share"),
                   2444:                (int) map, (int) (map->pmap), map->ref_count, map->nentries,
                   2445:                map->timestamp);
                   2446: 
                   2447:        if (!full && indent)
                   2448:                return;
                   2449: 
                   2450:        indent += 2;
                   2451:        for (entry = map->header.next; entry != &map->header;
                   2452:                                entry = entry->next) {
                   2453:                iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
                   2454:                        (int) entry, (int) entry->start, (int) entry->end);
                   2455:                if (map->is_main_map) {
                   2456:                        static char *inheritance_name[4] =
                   2457:                                { "share", "copy", "none", "donate_copy"};
                   2458:                        printf("prot=%x/%x/%s, ",
                   2459:                                entry->protection,
                   2460:                                entry->max_protection,
                   2461:                                inheritance_name[entry->inheritance]);
                   2462:                        if (entry->wired_count != 0)
                   2463:                                printf("wired, ");
                   2464:                }
                   2465: 
                   2466:                if (entry->is_a_map || entry->is_sub_map) {
                   2467:                        printf("share=0x%x, offset=0x%x\n",
                   2468:                                (int) entry->object.share_map,
                   2469:                                (int) entry->offset);
                   2470:                        if ((entry->prev == &map->header) ||
                   2471:                            (!entry->prev->is_a_map) ||
                   2472:                            (entry->prev->object.share_map !=
                   2473:                             entry->object.share_map)) {
                   2474:                                indent += 2;
                   2475:                                vm_map_print(entry->object.share_map, full);
                   2476:                                indent -= 2;
                   2477:                        }
                   2478:                                
                   2479:                }
                   2480:                else {
                   2481:                        printf("object=0x%x, offset=0x%x",
                   2482:                                (int) entry->object.vm_object,
                   2483:                                (int) entry->offset);
                   2484:                        if (entry->copy_on_write)
                   2485:                                printf(", copy (%s)",
                   2486:                                       entry->needs_copy ? "needed" : "done");
                   2487:                        printf("\n");
                   2488: 
                   2489:                        if ((entry->prev == &map->header) ||
                   2490:                            (entry->prev->is_a_map) ||
                   2491:                            (entry->prev->object.vm_object !=
                   2492:                             entry->object.vm_object)) {
                   2493:                                indent += 2;
                   2494:                                vm_object_print(entry->object.vm_object, full);
                   2495:                                indent -= 2;
                   2496:                        }
                   2497:                }
                   2498:        }
                   2499:        indent -= 2;
                   2500: }

unix.superglobalmegacorp.com

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