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

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

unix.superglobalmegacorp.com

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