Annotation of Gnu-Mach/vm/vm_kern.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
                      4:  * Copyright (c) 1993,1994 The University of Utah and
                      5:  * the Computer Systems Laboratory (CSL).
                      6:  * All rights reserved.
                      7:  *
                      8:  * Permission to use, copy, modify and distribute this software and its
                      9:  * documentation is hereby granted, provided that both the copyright
                     10:  * notice and this permission notice appear in all copies of the
                     11:  * software, derivative works or modified versions, and any portions
                     12:  * thereof, and that both notices appear in supporting documentation.
                     13:  *
                     14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
                     15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
                     16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
                     17:  * THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  [email protected]
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29: /*
                     30:  *     File:   vm/vm_kern.c
                     31:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     32:  *     Date:   1985
                     33:  *
                     34:  *     Kernel memory management.
                     35:  */
                     36: 
1.1.1.2   root       37: #include <string.h>
                     38: 
1.1       root       39: #include <mach/kern_return.h>
1.1.1.2   root       40: #include <machine/locore.h>
                     41: #include <machine/vm_param.h>
1.1       root       42: #include <kern/assert.h>
1.1.1.2   root       43: #include <kern/debug.h>
1.1       root       44: #include <kern/lock.h>
1.1.1.3 ! root       45: #include <kern/slab.h>
1.1       root       46: #include <kern/thread.h>
1.1.1.2   root       47: #include <kern/printf.h>
                     48: #include <vm/pmap.h>
1.1       root       49: #include <vm/vm_fault.h>
                     50: #include <vm/vm_kern.h>
                     51: #include <vm/vm_map.h>
                     52: #include <vm/vm_object.h>
                     53: #include <vm/vm_page.h>
                     54: #include <vm/vm_pageout.h>
                     55: 
                     56: 
                     57: 
                     58: /*
                     59:  *     Variables exported by this module.
                     60:  */
                     61: 
1.1.1.2   root       62: static struct vm_map   kernel_map_store;
                     63: vm_map_t               kernel_map = &kernel_map_store;
1.1       root       64: vm_map_t       kernel_pageable_map;
                     65: 
                     66: /*
                     67:  *     projected_buffer_allocate
                     68:  *
                     69:  *     Allocate a wired-down buffer shared between kernel and user task.  
                     70:  *      Fresh, zero-filled memory is allocated.
                     71:  *      If persistence is false, this buffer can only be deallocated from
                     72:  *      user task using projected_buffer_deallocate, and deallocation 
                     73:  *      from user task also deallocates the buffer from the kernel map.
                     74:  *      projected_buffer_collect is called from vm_map_deallocate to
                     75:  *      automatically deallocate projected buffers on task_deallocate.
                     76:  *      Sharing with more than one user task is achieved by using 
                     77:  *      projected_buffer_map for the second and subsequent tasks.
                     78:  *      The user is precluded from manipulating the VM entry of this buffer
                     79:  *      (i.e. changing protection, inheritance or machine attributes).
                     80:  */
                     81: 
                     82: kern_return_t
1.1.1.3 ! root       83: projected_buffer_allocate(
        !            84:        vm_map_t        map,
        !            85:        vm_size_t       size,
        !            86:        int             persistence,
        !            87:        vm_offset_t     *kernel_p,
        !            88:        vm_offset_t     *user_p,
        !            89:        vm_prot_t       protection,
        !            90:        vm_inherit_t    inheritance)  /*Currently only VM_INHERIT_NONE supported*/
1.1       root       91: {
                     92:        vm_object_t object;
                     93:        vm_map_entry_t u_entry, k_entry;
                     94:        vm_offset_t addr;
                     95:        vm_size_t r_size;
                     96:        kern_return_t kr;
                     97: 
                     98:        if (map == VM_MAP_NULL || map == kernel_map)
                     99:          return(KERN_INVALID_ARGUMENT);
                    100: 
                    101:        /*
                    102:         *      Allocate a new object. 
                    103:         */
                    104: 
                    105:        size = round_page(size);
                    106:        object = vm_object_allocate(size);
                    107: 
                    108:        vm_map_lock(kernel_map);
                    109:        kr = vm_map_find_entry(kernel_map, &addr, size, (vm_offset_t) 0,
                    110:                               VM_OBJECT_NULL, &k_entry);
                    111:        if (kr != KERN_SUCCESS) {
                    112:          vm_map_unlock(kernel_map);
                    113:          vm_object_deallocate(object);
                    114:          return kr;
                    115:        }
                    116: 
                    117:        k_entry->object.vm_object = object;
                    118:        if (!persistence)
                    119:          k_entry->projected_on = (vm_map_entry_t) -1;
                    120:               /*Mark entry so as to automatically deallocate it when
                    121:                 last corresponding user entry is deallocated*/
                    122:        vm_map_unlock(kernel_map);
                    123:        *kernel_p = addr;
                    124: 
                    125:        vm_map_lock(map);
                    126:        kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
                    127:                               VM_OBJECT_NULL, &u_entry);
                    128:        if (kr != KERN_SUCCESS) {
                    129:          vm_map_unlock(map);
                    130:          vm_map_lock(kernel_map);
                    131:          vm_map_entry_delete(kernel_map, k_entry);
                    132:          vm_map_unlock(kernel_map);
                    133:          vm_object_deallocate(object);
                    134:          return kr;
                    135:        }
                    136: 
                    137:        u_entry->object.vm_object = object;
                    138:        vm_object_reference(object);
                    139:        u_entry->projected_on = k_entry;
                    140:              /*Creates coupling with kernel mapping of the buffer, and
                    141:                also guarantees that user cannot directly manipulate
                    142:                buffer VM entry*/
                    143:        u_entry->protection = protection;
                    144:        u_entry->max_protection = protection;
                    145:        u_entry->inheritance = inheritance;
                    146:        vm_map_unlock(map);
                    147:                *user_p = addr;
                    148: 
                    149:        /*
                    150:         *      Allocate wired-down memory in the object,
                    151:         *      and enter it in the kernel pmap.
                    152:         */
                    153:        kmem_alloc_pages(object, 0,
                    154:                         *kernel_p, *kernel_p + size,
                    155:                         VM_PROT_READ | VM_PROT_WRITE);
1.1.1.2   root      156:        memset((void*) *kernel_p, 0, size);         /*Zero fill*/
1.1       root      157: 
                    158:        /* Set up physical mappings for user pmap */
                    159: 
                    160:        pmap_pageable(map->pmap, *user_p, *user_p + size, FALSE);
                    161:        for (r_size = 0; r_size < size; r_size += PAGE_SIZE) {
                    162:          addr = pmap_extract(kernel_pmap, *kernel_p + r_size);
                    163:          pmap_enter(map->pmap, *user_p + r_size, addr,
                    164:                     protection, TRUE);
                    165:        }
                    166: 
                    167:        return(KERN_SUCCESS);
                    168: }
                    169: 
                    170: 
                    171: /*
                    172:  *     projected_buffer_map
                    173:  *
                    174:  *     Map an area of kernel memory onto a task's address space.
                    175:  *      No new memory is allocated; the area must previously exist in the
                    176:  *      kernel memory map.
                    177:  */
                    178: 
                    179: kern_return_t
1.1.1.3 ! root      180: projected_buffer_map(
        !           181:        vm_map_t        map,
        !           182:        vm_offset_t     kernel_addr,
        !           183:        vm_size_t       size,
        !           184:        vm_offset_t     *user_p,
        !           185:        vm_prot_t       protection,
        !           186:        vm_inherit_t    inheritance)  /*Currently only VM_INHERIT_NONE supported*/
1.1       root      187: {
                    188:        vm_map_entry_t u_entry, k_entry;
                    189:        vm_offset_t physical_addr, user_addr;
                    190:        vm_size_t r_size;
                    191:        kern_return_t kr;
                    192: 
                    193:        /*
                    194:         *      Find entry in kernel map 
                    195:         */
                    196: 
                    197:        size = round_page(size);
                    198:        if (map == VM_MAP_NULL || map == kernel_map ||
                    199:            !vm_map_lookup_entry(kernel_map, kernel_addr, &k_entry) ||
                    200:            kernel_addr + size > k_entry->vme_end)
                    201:          return(KERN_INVALID_ARGUMENT);
                    202: 
                    203: 
                    204:        /*
                    205:          *     Create entry in user task
                    206:          */
                    207: 
                    208:        vm_map_lock(map);
                    209:        kr = vm_map_find_entry(map, &user_addr, size, (vm_offset_t) 0,
                    210:                               VM_OBJECT_NULL, &u_entry);
                    211:        if (kr != KERN_SUCCESS) {
                    212:          vm_map_unlock(map);
                    213:          return kr;
                    214:        }
                    215: 
                    216:        u_entry->object.vm_object = k_entry->object.vm_object;
                    217:        vm_object_reference(k_entry->object.vm_object);
                    218:        u_entry->offset = kernel_addr - k_entry->vme_start + k_entry->offset;
                    219:        u_entry->projected_on = k_entry;
                    220:              /*Creates coupling with kernel mapping of the buffer, and
                    221:                also guarantees that user cannot directly manipulate
                    222:                buffer VM entry*/
                    223:        u_entry->protection = protection;
                    224:        u_entry->max_protection = protection;
                    225:        u_entry->inheritance = inheritance;
                    226:        u_entry->wired_count = k_entry->wired_count;
                    227:        vm_map_unlock(map);
                    228:                *user_p = user_addr;
                    229: 
                    230:        /* Set up physical mappings for user pmap */
                    231: 
                    232:        pmap_pageable(map->pmap, user_addr, user_addr + size,
                    233:                      !k_entry->wired_count);
                    234:        for (r_size = 0; r_size < size; r_size += PAGE_SIZE) {
                    235:          physical_addr = pmap_extract(kernel_pmap, kernel_addr + r_size);
                    236:          pmap_enter(map->pmap, user_addr + r_size, physical_addr,
                    237:                     protection, k_entry->wired_count);
                    238:        }
                    239: 
                    240:        return(KERN_SUCCESS);
                    241: }
                    242: 
                    243: 
                    244: /*
                    245:  *     projected_buffer_deallocate
                    246:  *
                    247:  *     Unmap projected buffer from task's address space.
                    248:  *      May also unmap buffer from kernel map, if buffer is not
                    249:  *      persistent and only the kernel reference remains.
                    250:  */
                    251: 
                    252: kern_return_t
1.1.1.3 ! root      253: projected_buffer_deallocate(
        !           254:      vm_map_t          map,
        !           255:      vm_offset_t       start, 
        !           256:      vm_offset_t       end)
1.1       root      257: {
                    258:        vm_map_entry_t entry, k_entry;
                    259: 
1.1.1.3 ! root      260:        if (map == VM_MAP_NULL || map == kernel_map)
        !           261:                return KERN_INVALID_ARGUMENT;
        !           262: 
1.1       root      263:        vm_map_lock(map);
1.1.1.3 ! root      264:        if (!vm_map_lookup_entry(map, start, &entry) ||
1.1       root      265:            end > entry->vme_end ||
                    266:             /*Check corresponding kernel entry*/
                    267:            (k_entry = entry->projected_on) == 0) {
                    268:          vm_map_unlock(map);
                    269:          return(KERN_INVALID_ARGUMENT);
                    270:        }
                    271: 
                    272:        /*Prepare for deallocation*/
                    273:        if (entry->vme_start < start)
1.1.1.2   root      274:          _vm_map_clip_start(&map->hdr, entry, start);
1.1       root      275:        if (entry->vme_end > end)
1.1.1.2   root      276:          _vm_map_clip_end(&map->hdr, entry, end);
1.1       root      277:        if (map->first_free == entry)   /*Adjust first_free hint*/
                    278:          map->first_free = entry->vme_prev;
                    279:        entry->projected_on = 0;        /*Needed to allow deletion*/
                    280:        entry->wired_count = 0;         /*Avoid unwire fault*/
                    281:        vm_map_entry_delete(map, entry);
                    282:        vm_map_unlock(map);
                    283: 
                    284:        /*Check if the buffer is not persistent and only the 
                    285:           kernel mapping remains, and if so delete it*/
                    286:        vm_map_lock(kernel_map);
                    287:        if (k_entry->projected_on == (vm_map_entry_t) -1 &&
                    288:            k_entry->object.vm_object->ref_count == 1) {
                    289:          if (kernel_map->first_free == k_entry)
                    290:            kernel_map->first_free = k_entry->vme_prev;
                    291:          k_entry->projected_on = 0;    /*Allow unwire fault*/
                    292:          vm_map_entry_delete(kernel_map, k_entry);
                    293:        }
                    294:        vm_map_unlock(kernel_map);
                    295:        return(KERN_SUCCESS);
                    296: }
                    297: 
                    298: 
                    299: /*
                    300:  *     projected_buffer_collect
                    301:  *
                    302:  *     Unmap all projected buffers from task's address space.
                    303:  */
                    304: 
                    305: kern_return_t
1.1.1.3 ! root      306: projected_buffer_collect(vm_map_t map)
1.1       root      307: {
                    308:         vm_map_entry_t entry, next;
                    309: 
                    310:         if (map == VM_MAP_NULL || map == kernel_map)
                    311:          return(KERN_INVALID_ARGUMENT);
                    312: 
                    313:        for (entry = vm_map_first_entry(map);
                    314:             entry != vm_map_to_entry(map);
                    315:             entry = next) {
                    316:          next = entry->vme_next;
                    317:          if (entry->projected_on != 0)
                    318:            projected_buffer_deallocate(map, entry->vme_start, entry->vme_end);
                    319:        }
                    320:        return(KERN_SUCCESS);
                    321: }
                    322: 
                    323: 
                    324: /*
                    325:  *     projected_buffer_in_range
                    326:  *
                    327:  *     Verifies whether a projected buffer exists in the address range 
                    328:  *      given.
                    329:  */
                    330: 
                    331: boolean_t
1.1.1.3 ! root      332: projected_buffer_in_range(
        !           333:        vm_map_t        map,
        !           334:        vm_offset_t     start, 
        !           335:        vm_offset_t     end)
1.1       root      336: {
                    337:         vm_map_entry_t entry;
                    338: 
                    339:         if (map == VM_MAP_NULL || map == kernel_map)
                    340:          return(FALSE);
                    341: 
                    342:        /*Find first entry*/
                    343:        if (!vm_map_lookup_entry(map, start, &entry))
                    344:          entry = entry->vme_next;
                    345: 
                    346:        while (entry != vm_map_to_entry(map) && entry->projected_on == 0 &&
                    347:               entry->vme_start <= end) {
                    348:          entry = entry->vme_next;
                    349:        }
                    350:        return(entry != vm_map_to_entry(map) && entry->vme_start <= end);
                    351: }
                    352: 
                    353: 
                    354: /*
                    355:  *     kmem_alloc:
                    356:  *
                    357:  *     Allocate wired-down memory in the kernel's address map
                    358:  *     or a submap.  The memory is not zero-filled.
                    359:  */
                    360: 
                    361: kern_return_t
1.1.1.3 ! root      362: kmem_alloc(
        !           363:        vm_map_t        map,
        !           364:        vm_offset_t     *addrp,
        !           365:        vm_size_t       size)
1.1       root      366: {
                    367:        vm_object_t object;
                    368:        vm_map_entry_t entry;
                    369:        vm_offset_t addr;
1.1.1.3 ! root      370:        unsigned int attempts;
1.1       root      371:        kern_return_t kr;
                    372: 
                    373:        /*
                    374:         *      Allocate a new object.  We must do this before locking
                    375:         *      the map, lest we risk deadlock with the default pager:
                    376:         *              device_read_alloc uses kmem_alloc,
                    377:         *              which tries to allocate an object,
                    378:         *              which uses kmem_alloc_wired to get memory,
                    379:         *              which blocks for pages.
                    380:         *              then the default pager needs to read a block
                    381:         *              to process a memory_object_data_write,
                    382:         *              and device_read_alloc calls kmem_alloc
                    383:         *              and deadlocks on the map lock.
                    384:         */
                    385: 
                    386:        size = round_page(size);
                    387:        object = vm_object_allocate(size);
                    388: 
1.1.1.3 ! root      389:        attempts = 0;
        !           390: 
        !           391: retry:
1.1       root      392:        vm_map_lock(map);
                    393:        kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
                    394:                               VM_OBJECT_NULL, &entry);
                    395:        if (kr != KERN_SUCCESS) {
                    396:                vm_map_unlock(map);
1.1.1.3 ! root      397: 
        !           398:                if (attempts == 0) {
        !           399:                        attempts++;
        !           400:                        slab_collect();
        !           401:                        goto retry;
        !           402:                }
        !           403: 
        !           404:                printf_once("no more room for kmem_alloc in %p\n", map);
1.1       root      405:                vm_object_deallocate(object);
                    406:                return kr;
                    407:        }
                    408: 
                    409:        entry->object.vm_object = object;
                    410:        entry->offset = 0;
                    411: 
                    412:        /*
                    413:         *      Since we have not given out this address yet,
                    414:         *      it is safe to unlock the map.
                    415:         */
                    416:        vm_map_unlock(map);
                    417: 
                    418:        /*
                    419:         *      Allocate wired-down memory in the kernel_object,
                    420:         *      for this entry, and enter it in the kernel pmap.
                    421:         */
                    422:        kmem_alloc_pages(object, 0,
                    423:                         addr, addr + size,
                    424:                         VM_PROT_DEFAULT);
                    425: 
                    426:        /*
                    427:         *      Return the memory, not zeroed.
                    428:         */
                    429:        *addrp = addr;
                    430:        return KERN_SUCCESS;
                    431: }
                    432: 
                    433: /*
                    434:  *     kmem_realloc:
                    435:  *
                    436:  *     Reallocate wired-down memory in the kernel's address map
                    437:  *     or a submap.  Newly allocated pages are not zeroed.
                    438:  *     This can only be used on regions allocated with kmem_alloc.
                    439:  *
                    440:  *     If successful, the pages in the old region are mapped twice.
                    441:  *     The old region is unchanged.  Use kmem_free to get rid of it.
                    442:  */
1.1.1.3 ! root      443: kern_return_t kmem_realloc(
        !           444:        vm_map_t        map,
        !           445:        vm_offset_t     oldaddr,
        !           446:        vm_size_t       oldsize,
        !           447:        vm_offset_t     *newaddrp,
        !           448:        vm_size_t       newsize)
1.1       root      449: {
                    450:        vm_offset_t oldmin, oldmax;
                    451:        vm_offset_t newaddr;
                    452:        vm_object_t object;
                    453:        vm_map_entry_t oldentry, newentry;
1.1.1.3 ! root      454:        unsigned int attempts;
1.1       root      455:        kern_return_t kr;
                    456: 
                    457:        oldmin = trunc_page(oldaddr);
                    458:        oldmax = round_page(oldaddr + oldsize);
                    459:        oldsize = oldmax - oldmin;
                    460:        newsize = round_page(newsize);
                    461: 
                    462:        /*
                    463:         *      Find space for the new region.
                    464:         */
                    465: 
1.1.1.3 ! root      466:        attempts = 0;
        !           467: 
        !           468: retry:
1.1       root      469:        vm_map_lock(map);
                    470:        kr = vm_map_find_entry(map, &newaddr, newsize, (vm_offset_t) 0,
                    471:                               VM_OBJECT_NULL, &newentry);
                    472:        if (kr != KERN_SUCCESS) {
                    473:                vm_map_unlock(map);
1.1.1.3 ! root      474: 
        !           475:                if (attempts == 0) {
        !           476:                        attempts++;
        !           477:                        slab_collect();
        !           478:                        goto retry;
        !           479:                }
        !           480: 
1.1.1.2   root      481:                printf_once("no more room for kmem_realloc in %p\n", map);
1.1       root      482:                return kr;
                    483:        }
                    484: 
                    485:        /*
                    486:         *      Find the VM object backing the old region.
                    487:         */
                    488: 
                    489:        if (!vm_map_lookup_entry(map, oldmin, &oldentry))
                    490:                panic("kmem_realloc");
                    491:        object = oldentry->object.vm_object;
                    492: 
                    493:        /*
                    494:         *      Increase the size of the object and
                    495:         *      fill in the new region.
                    496:         */
                    497: 
                    498:        vm_object_reference(object);
                    499:        vm_object_lock(object);
                    500:        if (object->size != oldsize)
                    501:                panic("kmem_realloc");
                    502:        object->size = newsize;
                    503:        vm_object_unlock(object);
                    504: 
                    505:        newentry->object.vm_object = object;
                    506:        newentry->offset = 0;
                    507: 
                    508:        /*
                    509:         *      Since we have not given out this address yet,
                    510:         *      it is safe to unlock the map.  We are trusting
                    511:         *      that nobody will play with either region.
                    512:         */
                    513: 
                    514:        vm_map_unlock(map);
                    515: 
                    516:        /*
                    517:         *      Remap the pages in the old region and
                    518:         *      allocate more pages for the new region.
                    519:         */
                    520: 
                    521:        kmem_remap_pages(object, 0,
                    522:                         newaddr, newaddr + oldsize,
                    523:                         VM_PROT_DEFAULT);
                    524:        kmem_alloc_pages(object, oldsize,
                    525:                         newaddr + oldsize, newaddr + newsize,
                    526:                         VM_PROT_DEFAULT);
                    527: 
                    528:        *newaddrp = newaddr;
                    529:        return KERN_SUCCESS;
                    530: }
                    531: 
                    532: /*
                    533:  *     kmem_alloc_wired:
                    534:  *
                    535:  *     Allocate wired-down memory in the kernel's address map
                    536:  *     or a submap.  The memory is not zero-filled.
                    537:  *
                    538:  *     The memory is allocated in the kernel_object.
                    539:  *     It may not be copied with vm_map_copy, and
                    540:  *     it may not be reallocated with kmem_realloc.
                    541:  */
                    542: 
                    543: kern_return_t
1.1.1.3 ! root      544: kmem_alloc_wired(
        !           545:        vm_map_t        map,
        !           546:        vm_offset_t     *addrp,
        !           547:        vm_size_t       size)
1.1       root      548: {
                    549:        vm_map_entry_t entry;
                    550:        vm_offset_t offset;
                    551:        vm_offset_t addr;
1.1.1.3 ! root      552:        unsigned int attempts;
1.1       root      553:        kern_return_t kr;
                    554: 
                    555:        /*
                    556:         *      Use the kernel object for wired-down kernel pages.
                    557:         *      Assume that no region of the kernel object is
                    558:         *      referenced more than once.  We want vm_map_find_entry
                    559:         *      to extend an existing entry if possible.
                    560:         */
                    561: 
                    562:        size = round_page(size);
1.1.1.3 ! root      563:        attempts = 0;
        !           564: 
        !           565: retry:
1.1       root      566:        vm_map_lock(map);
                    567:        kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
                    568:                               kernel_object, &entry);
                    569:        if (kr != KERN_SUCCESS) {
                    570:                vm_map_unlock(map);
1.1.1.3 ! root      571: 
        !           572:                if (attempts == 0) {
        !           573:                        attempts++;
        !           574:                        slab_collect();
        !           575:                        goto retry;
        !           576:                }
        !           577: 
        !           578:                printf_once("no more room for kmem_alloc_wired in %p\n", map);
1.1       root      579:                return kr;
                    580:        }
                    581: 
                    582:        /*
                    583:         *      Since we didn't know where the new region would
                    584:         *      start, we couldn't supply the correct offset into
                    585:         *      the kernel object.  We only initialize the entry
                    586:         *      if we aren't extending an existing entry.
                    587:         */
                    588: 
                    589:        offset = addr - VM_MIN_KERNEL_ADDRESS;
                    590: 
                    591:        if (entry->object.vm_object == VM_OBJECT_NULL) {
                    592:                vm_object_reference(kernel_object);
                    593: 
                    594:                entry->object.vm_object = kernel_object;
                    595:                entry->offset = offset;
                    596:        }
                    597: 
                    598:        /*
                    599:         *      Since we have not given out this address yet,
                    600:         *      it is safe to unlock the map.
                    601:         */
                    602:        vm_map_unlock(map);
                    603: 
                    604:        /*
                    605:         *      Allocate wired-down memory in the kernel_object,
                    606:         *      for this entry, and enter it in the kernel pmap.
                    607:         */
                    608:        kmem_alloc_pages(kernel_object, offset,
                    609:                         addr, addr + size,
                    610:                         VM_PROT_DEFAULT);
                    611: 
                    612:        /*
                    613:         *      Return the memory, not zeroed.
                    614:         */
                    615:        *addrp = addr;
                    616:        return KERN_SUCCESS;
                    617: }
                    618: 
                    619: /*
                    620:  *     kmem_alloc_aligned:
                    621:  *
                    622:  *     Like kmem_alloc_wired, except that the memory is aligned.
                    623:  *     The size should be a power-of-2.
                    624:  */
                    625: 
                    626: kern_return_t
1.1.1.3 ! root      627: kmem_alloc_aligned(
        !           628:        vm_map_t        map,
        !           629:        vm_offset_t     *addrp,
        !           630:        vm_size_t       size)
1.1       root      631: {
                    632:        vm_map_entry_t entry;
                    633:        vm_offset_t offset;
                    634:        vm_offset_t addr;
1.1.1.3 ! root      635:        unsigned int attempts;
1.1       root      636:        kern_return_t kr;
                    637: 
                    638:        if ((size & (size - 1)) != 0)
                    639:                panic("kmem_alloc_aligned");
                    640: 
                    641:        /*
                    642:         *      Use the kernel object for wired-down kernel pages.
                    643:         *      Assume that no region of the kernel object is
                    644:         *      referenced more than once.  We want vm_map_find_entry
                    645:         *      to extend an existing entry if possible.
                    646:         */
                    647: 
                    648:        size = round_page(size);
1.1.1.3 ! root      649:        attempts = 0;
        !           650: 
        !           651: retry:
1.1       root      652:        vm_map_lock(map);
                    653:        kr = vm_map_find_entry(map, &addr, size, size - 1,
                    654:                               kernel_object, &entry);
                    655:        if (kr != KERN_SUCCESS) {
                    656:                vm_map_unlock(map);
1.1.1.3 ! root      657: 
        !           658:                if (attempts == 0) {
        !           659:                        attempts++;
        !           660:                        slab_collect();
        !           661:                        goto retry;
        !           662:                }
        !           663: 
        !           664:                printf_once("no more rooom for kmem_alloc_aligned in %p\n", map);
1.1       root      665:                return kr;
                    666:        }
                    667: 
                    668:        /*
                    669:         *      Since we didn't know where the new region would
                    670:         *      start, we couldn't supply the correct offset into
                    671:         *      the kernel object.  We only initialize the entry
                    672:         *      if we aren't extending an existing entry.
                    673:         */
                    674: 
                    675:        offset = addr - VM_MIN_KERNEL_ADDRESS;
                    676: 
                    677:        if (entry->object.vm_object == VM_OBJECT_NULL) {
                    678:                vm_object_reference(kernel_object);
                    679: 
                    680:                entry->object.vm_object = kernel_object;
                    681:                entry->offset = offset;
                    682:        }
                    683: 
                    684:        /*
                    685:         *      Since we have not given out this address yet,
                    686:         *      it is safe to unlock the map.
                    687:         */
                    688:        vm_map_unlock(map);
                    689: 
                    690:        /*
                    691:         *      Allocate wired-down memory in the kernel_object,
                    692:         *      for this entry, and enter it in the kernel pmap.
                    693:         */
                    694:        kmem_alloc_pages(kernel_object, offset,
                    695:                         addr, addr + size,
                    696:                         VM_PROT_DEFAULT);
                    697: 
                    698:        /*
                    699:         *      Return the memory, not zeroed.
                    700:         */
                    701:        *addrp = addr;
                    702:        return KERN_SUCCESS;
                    703: }
                    704: 
                    705: /*
                    706:  *     kmem_alloc_pageable:
                    707:  *
                    708:  *     Allocate pageable memory in the kernel's address map.
                    709:  */
                    710: 
                    711: kern_return_t
1.1.1.3 ! root      712: kmem_alloc_pageable(
        !           713:        vm_map_t        map,
        !           714:        vm_offset_t     *addrp,
        !           715:        vm_size_t       size)
1.1       root      716: {
                    717:        vm_offset_t addr;
                    718:        kern_return_t kr;
                    719: 
                    720:        addr = vm_map_min(map);
                    721:        kr = vm_map_enter(map, &addr, round_page(size),
                    722:                          (vm_offset_t) 0, TRUE,
                    723:                          VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
                    724:                          VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
1.1.1.2   root      725:        if (kr != KERN_SUCCESS) {
                    726:                printf_once("no more room for kmem_alloc_pageable in %p\n", map);
1.1       root      727:                return kr;
1.1.1.2   root      728:        }
1.1       root      729: 
                    730:        *addrp = addr;
                    731:        return KERN_SUCCESS;
                    732: }
                    733: 
                    734: /*
                    735:  *     kmem_free:
                    736:  *
                    737:  *     Release a region of kernel virtual memory allocated
                    738:  *     with kmem_alloc, kmem_alloc_wired, or kmem_alloc_pageable,
                    739:  *     and return the physical pages associated with that region.
                    740:  */
                    741: 
                    742: void
1.1.1.3 ! root      743: kmem_free(
        !           744:        vm_map_t        map,
        !           745:        vm_offset_t     addr,
        !           746:        vm_size_t       size)
1.1       root      747: {
                    748:        kern_return_t kr;
                    749: 
                    750:        kr = vm_map_remove(map, trunc_page(addr), round_page(addr + size));
                    751:        if (kr != KERN_SUCCESS)
                    752:                panic("kmem_free");
                    753: }
                    754: 
                    755: /*
                    756:  *     Allocate new wired pages in an object.
                    757:  *     The object is assumed to be mapped into the kernel map or
                    758:  *     a submap.
                    759:  */
                    760: void
1.1.1.3 ! root      761: kmem_alloc_pages(
        !           762:        vm_object_t     object,
        !           763:        vm_offset_t     offset,
        !           764:        vm_offset_t     start, 
        !           765:        vm_offset_t     end,
        !           766:        vm_prot_t       protection)
1.1       root      767: {
                    768:        /*
                    769:         *      Mark the pmap region as not pageable.
                    770:         */
                    771:        pmap_pageable(kernel_pmap, start, end, FALSE);
                    772: 
                    773:        while (start < end) {
1.1.1.3 ! root      774:            vm_page_t   mem;
1.1       root      775: 
                    776:            vm_object_lock(object);
                    777: 
                    778:            /*
                    779:             *  Allocate a page
                    780:             */
                    781:            while ((mem = vm_page_alloc(object, offset))
                    782:                         == VM_PAGE_NULL) {
                    783:                vm_object_unlock(object);
                    784:                VM_PAGE_WAIT((void (*)()) 0);
                    785:                vm_object_lock(object);
                    786:            }
                    787: 
                    788:            /*
                    789:             *  Wire it down
                    790:             */
                    791:            vm_page_lock_queues();
                    792:            vm_page_wire(mem);
                    793:            vm_page_unlock_queues();
                    794:            vm_object_unlock(object);
                    795: 
                    796:            /*
                    797:             *  Enter it in the kernel pmap
                    798:             */
                    799:            PMAP_ENTER(kernel_pmap, start, mem,
                    800:                       protection, TRUE);
                    801: 
                    802:            vm_object_lock(object);
                    803:            PAGE_WAKEUP_DONE(mem);
                    804:            vm_object_unlock(object);
                    805: 
                    806:            start += PAGE_SIZE;
                    807:            offset += PAGE_SIZE;
                    808:        }
                    809: }
                    810: 
                    811: /*
                    812:  *     Remap wired pages in an object into a new region.
                    813:  *     The object is assumed to be mapped into the kernel map or
                    814:  *     a submap.
                    815:  */
                    816: void
1.1.1.3 ! root      817: kmem_remap_pages(
        !           818:        vm_object_t     object,
        !           819:        vm_offset_t     offset,
        !           820:        vm_offset_t     start, 
        !           821:        vm_offset_t     end,
        !           822:        vm_prot_t       protection)
1.1       root      823: {
                    824:        /*
                    825:         *      Mark the pmap region as not pageable.
                    826:         */
                    827:        pmap_pageable(kernel_pmap, start, end, FALSE);
                    828: 
                    829:        while (start < end) {
1.1.1.3 ! root      830:            vm_page_t   mem;
1.1       root      831: 
                    832:            vm_object_lock(object);
                    833: 
                    834:            /*
                    835:             *  Find a page
                    836:             */
                    837:            if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
                    838:                panic("kmem_remap_pages");
                    839: 
                    840:            /*
                    841:             *  Wire it down (again)
                    842:             */
                    843:            vm_page_lock_queues();
                    844:            vm_page_wire(mem);
                    845:            vm_page_unlock_queues();
                    846:            vm_object_unlock(object);
                    847: 
                    848:            /*
                    849:             *  Enter it in the kernel pmap.  The page isn't busy,
                    850:             *  but this shouldn't be a problem because it is wired.
                    851:             */
                    852:            PMAP_ENTER(kernel_pmap, start, mem,
                    853:                       protection, TRUE);
                    854: 
                    855:            start += PAGE_SIZE;
                    856:            offset += PAGE_SIZE;
                    857:        }
                    858: }
                    859: 
                    860: /*
1.1.1.2   root      861:  *     kmem_submap:
1.1       root      862:  *
1.1.1.2   root      863:  *     Initializes a map to manage a subrange
1.1       root      864:  *     of the kernel virtual address space.
                    865:  *
                    866:  *     Arguments are as follows:
                    867:  *
1.1.1.2   root      868:  *     map             Map to initialize
1.1       root      869:  *     parent          Map to take range from
                    870:  *     size            Size of range to find
                    871:  *     min, max        Returned endpoints of map
                    872:  *     pageable        Can the region be paged
                    873:  */
                    874: 
1.1.1.2   root      875: void
1.1.1.3 ! root      876: kmem_submap(
        !           877:        vm_map_t        map, 
        !           878:        vm_map_t        parent,
        !           879:        vm_offset_t     *min, 
        !           880:        vm_offset_t     *max,
        !           881:        vm_size_t       size,
        !           882:        boolean_t       pageable)
1.1       root      883: {
                    884:        vm_offset_t addr;
                    885:        kern_return_t kr;
                    886: 
                    887:        size = round_page(size);
                    888: 
                    889:        /*
                    890:         *      Need reference on submap object because it is internal
                    891:         *      to the vm_system.  vm_object_enter will never be called
                    892:         *      on it (usual source of reference for vm_map_enter).
                    893:         */
                    894:        vm_object_reference(vm_submap_object);
                    895: 
1.1.1.3 ! root      896:        addr = vm_map_min(parent);
1.1       root      897:        kr = vm_map_enter(parent, &addr, size,
                    898:                          (vm_offset_t) 0, TRUE,
                    899:                          vm_submap_object, (vm_offset_t) 0, FALSE,
                    900:                          VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
                    901:        if (kr != KERN_SUCCESS)
1.1.1.2   root      902:                panic("kmem_submap");
1.1       root      903: 
                    904:        pmap_reference(vm_map_pmap(parent));
1.1.1.2   root      905:        vm_map_setup(map, vm_map_pmap(parent), addr, addr + size, pageable);
1.1       root      906:        kr = vm_map_submap(parent, addr, addr + size, map);
                    907:        if (kr != KERN_SUCCESS)
1.1.1.2   root      908:                panic("kmem_submap");
1.1       root      909: 
                    910:        *min = addr;
                    911:        *max = addr + size;
                    912: }
                    913: 
                    914: /*
                    915:  *     kmem_init:
                    916:  *
                    917:  *     Initialize the kernel's virtual memory map, taking
                    918:  *     into account all memory allocated up to this time.
                    919:  */
1.1.1.3 ! root      920: void kmem_init(
        !           921:        vm_offset_t     start,
        !           922:        vm_offset_t     end)
1.1       root      923: {
1.1.1.2   root      924:        vm_map_setup(kernel_map, pmap_kernel(), VM_MIN_KERNEL_ADDRESS, end,
                    925:                     FALSE);
1.1       root      926: 
                    927:        /*
                    928:         *      Reserve virtual memory allocated up to this time.
                    929:         */
                    930: 
                    931:        if (start != VM_MIN_KERNEL_ADDRESS) {
                    932:                kern_return_t rc;
                    933:                vm_offset_t addr = VM_MIN_KERNEL_ADDRESS;
                    934:                rc = vm_map_enter(kernel_map,
                    935:                                  &addr, start - VM_MIN_KERNEL_ADDRESS,
                    936:                                  (vm_offset_t) 0, TRUE,
                    937:                                  VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
                    938:                                  VM_PROT_DEFAULT, VM_PROT_ALL,
                    939:                                  VM_INHERIT_DEFAULT);
                    940:                if (rc)
                    941:                        panic("%s:%d: vm_map_enter failed (%d)\n", rc);
                    942:        }
                    943: }
                    944: 
                    945: /*
                    946:  *     New and improved IO wiring support.
                    947:  */
                    948: 
                    949: /*
                    950:  *     kmem_io_map_copyout:
                    951:  *
                    952:  *     Establish temporary mapping in designated map for the memory
                    953:  *     passed in.  Memory format must be a page_list vm_map_copy.
                    954:  *     Mapping is READ-ONLY.
                    955:  */
                    956: 
                    957: kern_return_t
1.1.1.3 ! root      958: kmem_io_map_copyout(
        !           959:      vm_map_t          map,
        !           960:      vm_offset_t       *addr,          /* actual addr of data */
        !           961:      vm_offset_t       *alloc_addr,    /* page aligned addr */
        !           962:      vm_size_t         *alloc_size,    /* size allocated */
        !           963:      vm_map_copy_t     copy,
        !           964:      vm_size_t         min_size)       /* Do at least this much */
1.1       root      965: {
                    966:        vm_offset_t     myaddr, offset;
                    967:        vm_size_t       mysize, copy_size;
                    968:        kern_return_t   ret;
                    969:        vm_page_t       *page_list;
                    970:        vm_map_copy_t   new_copy;
                    971:        int             i;
                    972: 
                    973:        assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                    974:        assert(min_size != 0);
                    975: 
                    976:        /*
                    977:         *      Figure out the size in vm pages.
                    978:         */
                    979:        min_size += copy->offset - trunc_page(copy->offset);
                    980:        min_size = round_page(min_size);
                    981:        mysize = round_page(copy->offset + copy->size) -
                    982:                trunc_page(copy->offset);
                    983: 
                    984:        /*
                    985:         *      If total size is larger than one page list and
                    986:         *      we don't have to do more than one page list, then
                    987:         *      only do one page list.  
                    988:         *
                    989:         * XXX  Could be much smarter about this ... like trimming length
                    990:         * XXX  if we need more than one page list but not all of them.
                    991:         */
                    992: 
                    993:        copy_size = ptoa(copy->cpy_npages);
                    994:        if (mysize > copy_size && copy_size > min_size)
                    995:                mysize = copy_size;
                    996: 
                    997:        /*
                    998:         *      Allocate some address space in the map (must be kernel
                    999:         *      space).
                   1000:         */
                   1001:        myaddr = vm_map_min(map);
                   1002:        ret = vm_map_enter(map, &myaddr, mysize,
                   1003:                          (vm_offset_t) 0, TRUE,
                   1004:                          VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
                   1005:                          VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
                   1006: 
                   1007:        if (ret != KERN_SUCCESS)
                   1008:                return(ret);
                   1009: 
                   1010:        /*
                   1011:         *      Tell the pmap module that this will be wired, and
                   1012:         *      enter the mappings.
                   1013:         */
                   1014:        pmap_pageable(vm_map_pmap(map), myaddr, myaddr + mysize, TRUE);
                   1015: 
                   1016:        *addr = myaddr + (copy->offset - trunc_page(copy->offset));
                   1017:        *alloc_addr = myaddr;
                   1018:        *alloc_size = mysize;
                   1019: 
                   1020:        offset = myaddr;
                   1021:        page_list = &copy->cpy_page_list[0];
                   1022:        while (TRUE) {
                   1023:                for ( i = 0; i < copy->cpy_npages; i++, offset += PAGE_SIZE) {
                   1024:                        PMAP_ENTER(vm_map_pmap(map), offset, *page_list,
                   1025:                                   VM_PROT_READ, TRUE);
                   1026:                        page_list++;
                   1027:                }
                   1028: 
                   1029:                if (offset == (myaddr + mysize))
                   1030:                        break;
                   1031: 
                   1032:                /*
                   1033:                 *      Onward to the next page_list.  The extend_cont
                   1034:                 *      leaves the current page list's pages alone; 
                   1035:                 *      they'll be cleaned up at discard.  Reset this
                   1036:                 *      copy's continuation to discard the next one.
                   1037:                 */
                   1038:                vm_map_copy_invoke_extend_cont(copy, &new_copy, &ret);
                   1039: 
                   1040:                if (ret != KERN_SUCCESS) {
                   1041:                        kmem_io_map_deallocate(map, myaddr, mysize);
                   1042:                        return(ret);
                   1043:                }
                   1044:                copy->cpy_cont = vm_map_copy_discard_cont;
                   1045:                copy->cpy_cont_args = (char *) new_copy;
                   1046:                copy = new_copy;
                   1047:                page_list = &copy->cpy_page_list[0];
                   1048:        }
                   1049: 
                   1050:        return(ret);
                   1051: }
                   1052: 
                   1053: /*
                   1054:  *     kmem_io_map_deallocate:
                   1055:  *
                   1056:  *     Get rid of the mapping established by kmem_io_map_copyout.
                   1057:  *     Assumes that addr and size have been rounded to page boundaries.
                   1058:  *     (e.g., the alloc_addr and alloc_size returned by kmem_io_map_copyout)
                   1059:  */
                   1060: 
                   1061: void
1.1.1.3 ! root     1062: kmem_io_map_deallocate(
        !          1063:        vm_map_t        map,
        !          1064:        vm_offset_t     addr,
        !          1065:        vm_size_t       size)
1.1       root     1066: {
                   1067:        /*
                   1068:         *      Remove the mappings.  The pmap_remove is needed.
                   1069:         */
                   1070:        
                   1071:        pmap_remove(vm_map_pmap(map), addr, addr + size);
                   1072:        vm_map_remove(map, addr, addr + size);
                   1073: }
                   1074: 
                   1075: /*
                   1076:  *     Routine:        copyinmap
                   1077:  *     Purpose:
                   1078:  *             Like copyin, except that fromaddr is an address
                   1079:  *             in the specified VM map.  This implementation
                   1080:  *             is incomplete; it handles the current user map
                   1081:  *             and the kernel map/submaps.
                   1082:  */
                   1083: 
1.1.1.3 ! root     1084: int copyinmap(
        !          1085:        vm_map_t        map,
        !          1086:        char            *fromaddr, 
        !          1087:        char            *toaddr,
        !          1088:        int             length)
1.1       root     1089: {
                   1090:        if (vm_map_pmap(map) == kernel_pmap) {
                   1091:                /* assume a correct copy */
1.1.1.2   root     1092:                memcpy(toaddr, fromaddr, length);
1.1       root     1093:                return 0;
                   1094:        }
                   1095: 
                   1096:        if (current_map() == map)
                   1097:                return copyin( fromaddr, toaddr, length);
                   1098: 
                   1099:        return 1;
                   1100: }
                   1101: 
                   1102: /*
                   1103:  *     Routine:        copyoutmap
                   1104:  *     Purpose:
                   1105:  *             Like copyout, except that toaddr is an address
                   1106:  *             in the specified VM map.  This implementation
                   1107:  *             is incomplete; it handles the current user map
                   1108:  *             and the kernel map/submaps.
                   1109:  */
                   1110: 
1.1.1.3 ! root     1111: int copyoutmap(
        !          1112:        vm_map_t map,
        !          1113:        char    *fromaddr, 
        !          1114:        char    *toaddr,
        !          1115:        int     length)
1.1       root     1116: {
                   1117:        if (vm_map_pmap(map) == kernel_pmap) {
                   1118:                /* assume a correct copy */
1.1.1.2   root     1119:                memcpy(toaddr, fromaddr, length);
1.1       root     1120:                return 0;
                   1121:        }
                   1122: 
                   1123:        if (current_map() == map)
                   1124:                return copyout(fromaddr, toaddr, length);
                   1125: 
                   1126:        return 1;
                   1127: }

unix.superglobalmegacorp.com

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