Annotation of OSKit-Mach/vm/vm_kern.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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