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

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

unix.superglobalmegacorp.com

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