Annotation of XNU/osfmk/vm/vm_kern.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: /*
                     53:  *     File:   vm/vm_kern.c
                     54:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     55:  *     Date:   1985
                     56:  *
                     57:  *     Kernel memory management.
                     58:  */
                     59: 
                     60: #include <cpus.h>
                     61: #include <mach/kern_return.h>
                     62: #include <mach/vm_param.h>
                     63: #include <kern/assert.h>
                     64: #include <kern/lock.h>
                     65: #include <kern/thread.h>
                     66: #include <vm/vm_kern.h>
                     67: #include <vm/vm_map.h>
                     68: #include <vm/vm_object.h>
                     69: #include <vm/vm_page.h>
                     70: #include <vm/vm_pageout.h>
                     71: #include <kern/misc_protos.h>
                     72: #include <vm/cpm.h>
                     73: 
                     74: #include <string.h>
                     75: /*
                     76:  *     Variables exported by this module.
                     77:  */
                     78: 
                     79: vm_map_t       kernel_map;
                     80: vm_map_t       kernel_pageable_map;
                     81: 
                     82: /*
                     83:  * Forward declarations for internal functions.
                     84:  */
                     85: extern kern_return_t kmem_alloc_pages(
                     86:        register vm_object_t    object,
                     87:        register vm_offset_t    offset,
                     88:        register vm_offset_t    start,
                     89:        register vm_offset_t    end,
                     90:        vm_prot_t               protection);
                     91: 
                     92: extern void kmem_remap_pages(
                     93:        register vm_object_t    object,
                     94:        register vm_offset_t    offset,
                     95:        register vm_offset_t    start,
                     96:        register vm_offset_t    end,
                     97:        vm_prot_t               protection);
                     98: 
                     99: kern_return_t
                    100: kmem_alloc_contig(
                    101:        vm_map_t        map,
                    102:        vm_offset_t     *addrp,
                    103:        vm_size_t       size,
                    104:        vm_offset_t     mask,
                    105:        int             flags)
                    106: {
                    107:        vm_object_t             object;
                    108:        vm_page_t               m, pages;
                    109:        kern_return_t           kr;
                    110:        vm_offset_t             addr, i, offset;
                    111:        vm_map_entry_t          entry;
                    112: 
                    113:        if (map == VM_MAP_NULL || (flags && (flags ^ KMA_KOBJECT))) 
                    114:                return KERN_INVALID_ARGUMENT;
                    115:        
                    116:        if (size == 0) {
                    117:                *addrp = 0;
                    118:                return KERN_INVALID_ARGUMENT;
                    119:        }
                    120: 
                    121:        size = round_page(size);
                    122:        if ((flags & KMA_KOBJECT) == 0) {
                    123:                object = vm_object_allocate(size);
                    124:                kr = vm_map_find_space(map, &addr, size, mask, &entry);
                    125:        }
                    126:        else {
                    127:                object = kernel_object;
                    128:                kr = vm_map_find_space(map, &addr, size, mask, &entry);
                    129:        }
                    130: 
                    131:        if ((flags & KMA_KOBJECT) == 0) {
                    132:                entry->object.vm_object = object;
                    133:                entry->offset = offset = 0;
                    134:        } else {
                    135:                offset = addr - VM_MIN_KERNEL_ADDRESS;
                    136: 
                    137:                if (entry->object.vm_object == VM_OBJECT_NULL) {
                    138:                        vm_object_reference(object);
                    139:                        entry->object.vm_object = object;
                    140:                        entry->offset = offset;
                    141:                }
                    142:        }
                    143: 
                    144:        if (kr != KERN_SUCCESS) {
                    145:                if ((flags & KMA_KOBJECT) == 0)
                    146:                        vm_object_deallocate(object);
                    147:                return kr;
                    148:        }
                    149: 
                    150:        vm_map_unlock(map);
                    151: 
                    152:        kr = cpm_allocate(size, &pages, FALSE);
                    153: 
                    154:        if (kr != KERN_SUCCESS) {
                    155:                vm_map_remove(map, addr, addr + size, 0);
                    156:                *addrp = 0;
                    157:                return kr;
                    158:        }
                    159: 
                    160:        vm_object_lock(object);
                    161:        for (i = 0; i < size; i += PAGE_SIZE) {
                    162:                m = pages;
                    163:                pages = NEXT_PAGE(m);
                    164:                m->busy = FALSE;
                    165:                vm_page_insert(m, object, offset + i);
                    166:        }
                    167:        vm_object_unlock(object);
                    168: 
                    169:        if ((kr = vm_map_wire(map, addr, addr + size, VM_PROT_DEFAULT, FALSE)) 
                    170:                != KERN_SUCCESS) {
                    171:                if (object == kernel_object) {
                    172:                        vm_object_lock(object);
                    173:                        vm_object_page_remove(object, offset, offset + size);
                    174:                        vm_object_unlock(object);
                    175:                }
                    176:                vm_map_remove(map, addr, addr + size, 0);
                    177:                return kr;
                    178:        }
                    179:        if (object == kernel_object)
                    180:                vm_map_simplify(map, addr);
                    181: 
                    182:        *addrp = addr;
                    183:        return KERN_SUCCESS;
                    184: }
                    185: 
                    186: /*
                    187:  * Master entry point for allocating kernel memory.
                    188:  * NOTE: this routine is _never_ interrupt safe.
                    189:  *
                    190:  * map         : map to allocate into
                    191:  * addrp       : pointer to start address of new memory
                    192:  * size                : size of memory requested
                    193:  * flags       : options
                    194:  *               KMA_HERE              *addrp is base address, else "anywhere"
                    195:  *               KMA_NOPAGEWAIT        don't wait for pages if unavailable
                    196:  *               KMA_KOBJECT           use kernel_object
                    197:  */
                    198: 
                    199: kern_return_t
                    200: kernel_memory_allocate(
                    201:        register vm_map_t       map,
                    202:        register vm_offset_t    *addrp,
                    203:        register vm_size_t      size,
                    204:        register vm_offset_t    mask,
                    205:        int                     flags)
                    206: {
                    207:        vm_object_t object = VM_OBJECT_NULL;
                    208:        vm_map_entry_t entry;
                    209:        vm_offset_t offset;
                    210:        vm_offset_t addr;
                    211:        vm_offset_t i;
                    212:        kern_return_t kr;
                    213: 
                    214:        size = round_page(size);
                    215:        if ((flags & KMA_KOBJECT) == 0) {
                    216:                /*
                    217:                 *      Allocate a new object.  We must do this before locking
                    218:                 *      the map, or risk deadlock with the default pager:
                    219:                 *              device_read_alloc uses kmem_alloc,
                    220:                 *              which tries to allocate an object,
                    221:                 *              which uses kmem_alloc_wired to get memory,
                    222:                 *              which blocks for pages.
                    223:                 *              then the default pager needs to read a block
                    224:                 *              to process a memory_object_data_write,
                    225:                 *              and device_read_alloc calls kmem_alloc
                    226:                 *              and deadlocks on the map lock.
                    227:                 */
                    228:                object = vm_object_allocate(size);
                    229:                kr = vm_map_find_space(map, &addr, size, mask, &entry);
                    230:        }
                    231:        else {
                    232:                object = kernel_object;
                    233:                kr = vm_map_find_space(map, &addr, size, mask, &entry);
                    234:        }
                    235:        if (kr != KERN_SUCCESS) {
                    236:                if ((flags & KMA_KOBJECT) == 0)
                    237:                        vm_object_deallocate(object);
                    238:                return kr;
                    239:        }
                    240: 
                    241:        if ((flags & KMA_KOBJECT) == 0) {
                    242:                entry->object.vm_object = object;
                    243:                entry->offset = offset = 0;
                    244:        } else {
                    245:                offset = addr - VM_MIN_KERNEL_ADDRESS;
                    246: 
                    247:                if (entry->object.vm_object == VM_OBJECT_NULL) {
                    248:                        vm_object_reference(object);
                    249:                        entry->object.vm_object = object;
                    250:                        entry->offset = offset;
                    251:                }
                    252:        }
                    253: 
                    254:        /*
                    255:         *      Since we have not given out this address yet,
                    256:         *      it is safe to unlock the map.
                    257:         */
                    258:        vm_map_unlock(map);
                    259: 
                    260:        vm_object_lock(object);
                    261:        for (i = 0; i < size; i += PAGE_SIZE) {
                    262:                vm_page_t       mem;
                    263: 
                    264:                while ((mem = vm_page_alloc(object, offset + i))
                    265:                            == VM_PAGE_NULL) {
                    266:                        if (flags & KMA_NOPAGEWAIT) {
                    267:                                if (object == kernel_object)
                    268:                                        vm_object_page_remove(object, offset,
                    269:                                                offset + i);
                    270:                                vm_object_unlock(object);
                    271:                                vm_map_remove(map, addr, addr + size, 0);
                    272:                                return KERN_RESOURCE_SHORTAGE;
                    273:                        }
                    274:                        vm_object_unlock(object);
                    275:                        VM_PAGE_WAIT();
                    276:                        vm_object_lock(object);
                    277:                }
                    278:                mem->busy = FALSE;
                    279:        }
                    280:        vm_object_unlock(object);
                    281: 
                    282:        if ((kr = vm_map_wire(map, addr, addr + size, VM_PROT_DEFAULT, FALSE)) 
                    283:                != KERN_SUCCESS) {
                    284:                if (object == kernel_object) {
                    285:                        vm_object_lock(object);
                    286:                        vm_object_page_remove(object, offset, offset + size);
                    287:                        vm_object_unlock(object);
                    288:                }
                    289:                vm_map_remove(map, addr, addr + size, 0);
                    290:                return (kr);
                    291:        }
                    292:        if (object == kernel_object)
                    293:                vm_map_simplify(map, addr);
                    294: 
                    295:        /*
                    296:         *      Return the memory, not zeroed.
                    297:         */
                    298: #if    (NCPUS > 1)  &&  i860
                    299:        bzero( addr, size );
                    300: #endif                                  /* #if (NCPUS > 1)  &&  i860 */
                    301:        *addrp = addr;
                    302:        return KERN_SUCCESS;
                    303: }
                    304: 
                    305: /*
                    306:  *     kmem_alloc:
                    307:  *
                    308:  *     Allocate wired-down memory in the kernel's address map
                    309:  *     or a submap.  The memory is not zero-filled.
                    310:  */
                    311: 
                    312: kern_return_t
                    313: kmem_alloc(
                    314:        vm_map_t        map,
                    315:        vm_offset_t     *addrp,
                    316:        vm_size_t       size)
                    317: {
                    318:        return kernel_memory_allocate(map, addrp, size, 0, 0);
                    319: }
                    320: 
                    321: /*
                    322:  *     kmem_realloc:
                    323:  *
                    324:  *     Reallocate wired-down memory in the kernel's address map
                    325:  *     or a submap.  Newly allocated pages are not zeroed.
                    326:  *     This can only be used on regions allocated with kmem_alloc.
                    327:  *
                    328:  *     If successful, the pages in the old region are mapped twice.
                    329:  *     The old region is unchanged.  Use kmem_free to get rid of it.
                    330:  */
                    331: kern_return_t
                    332: kmem_realloc(
                    333:        vm_map_t        map,
                    334:        vm_offset_t     oldaddr,
                    335:        vm_size_t       oldsize,
                    336:        vm_offset_t     *newaddrp,
                    337:        vm_size_t       newsize)
                    338: {
                    339:        vm_offset_t oldmin, oldmax;
                    340:        vm_offset_t newaddr;
                    341:        vm_object_t object;
                    342:        vm_map_entry_t oldentry, newentry;
                    343:        kern_return_t kr;
                    344: 
                    345:        oldmin = trunc_page(oldaddr);
                    346:        oldmax = round_page(oldaddr + oldsize);
                    347:        oldsize = oldmax - oldmin;
                    348:        newsize = round_page(newsize);
                    349: 
                    350:        /*
                    351:         *      Find space for the new region.
                    352:         */
                    353: 
                    354:        kr = vm_map_find_space(map, &newaddr, newsize, (vm_offset_t) 0,
                    355:                               &newentry);
                    356:        if (kr != KERN_SUCCESS) {
                    357:                return kr;
                    358:        }
                    359: 
                    360:        /*
                    361:         *      Find the VM object backing the old region.
                    362:         */
                    363: 
                    364:        if (!vm_map_lookup_entry(map, oldmin, &oldentry))
                    365:                panic("kmem_realloc");
                    366:        object = oldentry->object.vm_object;
                    367: 
                    368:        /*
                    369:         *      Increase the size of the object and
                    370:         *      fill in the new region.
                    371:         */
                    372: 
                    373:        vm_object_reference(object);
                    374:        vm_object_lock(object);
                    375:        if (object->size != oldsize)
                    376:                panic("kmem_realloc");
                    377:        object->size = newsize;
                    378:        vm_object_unlock(object);
                    379: 
                    380:        newentry->object.vm_object = object;
                    381:        newentry->offset = 0;
                    382:        assert (newentry->wired_count == 0);
                    383:        newentry->wired_count = 1;
                    384: 
                    385:        /*
                    386:         *      Since we have not given out this address yet,
                    387:         *      it is safe to unlock the map.  We are trusting
                    388:         *      that nobody will play with either region.
                    389:         */
                    390: 
                    391:        vm_map_unlock(map);
                    392: 
                    393:        /*
                    394:         *      Remap the pages in the old region and
                    395:         *      allocate more pages for the new region.
                    396:         */
                    397: 
                    398:        kmem_remap_pages(object, 0,
                    399:                         newaddr, newaddr + oldsize,
                    400:                         VM_PROT_DEFAULT);
                    401:        kmem_alloc_pages(object, oldsize,
                    402:                         newaddr + oldsize, newaddr + newsize,
                    403:                         VM_PROT_DEFAULT);
                    404: 
                    405:        *newaddrp = newaddr;
                    406:        return KERN_SUCCESS;
                    407: }
                    408: 
                    409: /*
                    410:  *     kmem_alloc_wired:
                    411:  *
                    412:  *     Allocate wired-down memory in the kernel's address map
                    413:  *     or a submap.  The memory is not zero-filled.
                    414:  *
                    415:  *     The memory is allocated in the kernel_object.
                    416:  *     It may not be copied with vm_map_copy, and
                    417:  *     it may not be reallocated with kmem_realloc.
                    418:  */
                    419: 
                    420: kern_return_t
                    421: kmem_alloc_wired(
                    422:        vm_map_t        map,
                    423:        vm_offset_t     *addrp,
                    424:        vm_size_t       size)
                    425: {
                    426:        return kernel_memory_allocate(map, addrp, size, 0, KMA_KOBJECT);
                    427: }
                    428: 
                    429: /*
                    430:  *     kmem_alloc_aligned:
                    431:  *
                    432:  *     Like kmem_alloc_wired, except that the memory is aligned.
                    433:  *     The size should be a power-of-2.
                    434:  */
                    435: 
                    436: kern_return_t
                    437: kmem_alloc_aligned(
                    438:        vm_map_t        map,
                    439:        vm_offset_t     *addrp,
                    440:        vm_size_t       size)
                    441: {
                    442:        if ((size & (size - 1)) != 0)
                    443:                panic("kmem_alloc_aligned: size not aligned");
                    444:        return kernel_memory_allocate(map, addrp, size, size - 1, KMA_KOBJECT);
                    445: }
                    446: 
                    447: /*
                    448:  *     kmem_alloc_pageable:
                    449:  *
                    450:  *     Allocate pageable memory in the kernel's address map.
                    451:  */
                    452: 
                    453: kern_return_t
                    454: kmem_alloc_pageable(
                    455:        vm_map_t        map,
                    456:        vm_offset_t     *addrp,
                    457:        vm_size_t       size)
                    458: {
                    459:        vm_offset_t addr;
                    460:        kern_return_t kr;
                    461: 
                    462:        addr = vm_map_min(map);
                    463:        kr = vm_map_enter(map, &addr, round_page(size),
                    464:                          (vm_offset_t) 0, TRUE,
                    465:                          VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
                    466:                          VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
                    467:        if (kr != KERN_SUCCESS)
                    468:                return kr;
                    469: 
                    470:        *addrp = addr;
                    471:        return KERN_SUCCESS;
                    472: }
                    473: 
                    474: /*
                    475:  *     kmem_free:
                    476:  *
                    477:  *     Release a region of kernel virtual memory allocated
                    478:  *     with kmem_alloc, kmem_alloc_wired, or kmem_alloc_pageable,
                    479:  *     and return the physical pages associated with that region.
                    480:  */
                    481: 
                    482: void
                    483: kmem_free(
                    484:        vm_map_t        map,
                    485:        vm_offset_t     addr,
                    486:        vm_size_t       size)
                    487: {
                    488:        kern_return_t kr;
                    489: 
                    490:        kr = vm_map_remove(map, trunc_page(addr),
                    491:                           round_page(addr + size), VM_MAP_REMOVE_KUNWIRE);
                    492:        if (kr != KERN_SUCCESS)
                    493:                panic("kmem_free");
                    494: }
                    495: 
                    496: /*
                    497:  *     Allocate new wired pages in an object.
                    498:  *     The object is assumed to be mapped into the kernel map or
                    499:  *     a submap.
                    500:  */
                    501: 
                    502: kern_return_t
                    503: kmem_alloc_pages(
                    504:        register vm_object_t    object,
                    505:        register vm_offset_t    offset,
                    506:        register vm_offset_t    start,
                    507:        register vm_offset_t    end,
                    508:        vm_prot_t               protection)
                    509: {
                    510:        /*
                    511:         *      Mark the pmap region as not pageable.
                    512:         */
                    513:        pmap_pageable(kernel_pmap, start, end, FALSE);
                    514: 
                    515:        while (start < end) {
                    516:            register vm_page_t  mem;
                    517: 
                    518:            vm_object_lock(object);
                    519: 
                    520:            /*
                    521:             *  Allocate a page
                    522:             */
                    523:            while ((mem = vm_page_alloc(object, offset))
                    524:                         == VM_PAGE_NULL) {
                    525:                vm_object_unlock(object);
                    526:                VM_PAGE_WAIT();
                    527:                vm_object_lock(object);
                    528:            }
                    529: 
                    530:            /*
                    531:             *  Wire it down
                    532:             */
                    533:            vm_page_lock_queues();
                    534:            vm_page_wire(mem);
                    535:            vm_page_unlock_queues();
                    536:            vm_object_unlock(object);
                    537: 
                    538:            /*
                    539:             *  Enter it in the kernel pmap
                    540:             */
                    541:            PMAP_ENTER(kernel_pmap, start, mem,
                    542:                       protection, TRUE);
                    543: 
                    544:            vm_object_lock(object);
                    545:            PAGE_WAKEUP_DONE(mem);
                    546:            vm_object_unlock(object);
                    547: 
                    548:            start += PAGE_SIZE;
                    549:            offset += PAGE_SIZE;
                    550:        }
                    551:        return KERN_SUCCESS;
                    552: }
                    553: 
                    554: /*
                    555:  *     Remap wired pages in an object into a new region.
                    556:  *     The object is assumed to be mapped into the kernel map or
                    557:  *     a submap.
                    558:  */
                    559: void
                    560: kmem_remap_pages(
                    561:        register vm_object_t    object,
                    562:        register vm_offset_t    offset,
                    563:        register vm_offset_t    start,
                    564:        register vm_offset_t    end,
                    565:        vm_prot_t               protection)
                    566: {
                    567:        /*
                    568:         *      Mark the pmap region as not pageable.
                    569:         */
                    570:        pmap_pageable(kernel_pmap, start, end, FALSE);
                    571: 
                    572:        while (start < end) {
                    573:            register vm_page_t  mem;
                    574: 
                    575:            vm_object_lock(object);
                    576: 
                    577:            /*
                    578:             *  Find a page
                    579:             */
                    580:            if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
                    581:                panic("kmem_remap_pages");
                    582: 
                    583:            /*
                    584:             *  Wire it down (again)
                    585:             */
                    586:            vm_page_lock_queues();
                    587:            vm_page_wire(mem);
                    588:            vm_page_unlock_queues();
                    589:            vm_object_unlock(object);
                    590: 
                    591:            /*
                    592:             *  Enter it in the kernel pmap.  The page isn't busy,
                    593:             *  but this shouldn't be a problem because it is wired.
                    594:             */
                    595:            PMAP_ENTER(kernel_pmap, start, mem,
                    596:                       protection, TRUE);
                    597: 
                    598:            start += PAGE_SIZE;
                    599:            offset += PAGE_SIZE;
                    600:        }
                    601: }
                    602: 
                    603: /*
                    604:  *     kmem_suballoc:
                    605:  *
                    606:  *     Allocates a map to manage a subrange
                    607:  *     of the kernel virtual address space.
                    608:  *
                    609:  *     Arguments are as follows:
                    610:  *
                    611:  *     parent          Map to take range from
                    612:  *     addr            Address of start of range (IN/OUT)
                    613:  *     size            Size of range to find
                    614:  *     pageable        Can region be paged
                    615:  *     anywhere        Can region be located anywhere in map
                    616:  *     new_map         Pointer to new submap
                    617:  */
                    618: kern_return_t
                    619: kmem_suballoc(
                    620:        vm_map_t        parent,
                    621:        vm_offset_t     *addr,
                    622:        vm_size_t       size,
                    623:        boolean_t       pageable,
                    624:        boolean_t       anywhere,
                    625:        vm_map_t        *new_map)
                    626: {
                    627:        vm_map_t map;
                    628:        kern_return_t kr;
                    629: 
                    630:        size = round_page(size);
                    631: 
                    632:        /*
                    633:         *      Need reference on submap object because it is internal
                    634:         *      to the vm_system.  vm_object_enter will never be called
                    635:         *      on it (usual source of reference for vm_map_enter).
                    636:         */
                    637:        vm_object_reference(vm_submap_object);
                    638: 
                    639:        if (anywhere == TRUE)
                    640:                *addr = (vm_offset_t)vm_map_min(parent);
                    641:        kr = vm_map_enter(parent, addr, size,
                    642:                          (vm_offset_t) 0, anywhere,
                    643:                          vm_submap_object, (vm_offset_t) 0, FALSE,
                    644:                          VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
                    645:        if (kr != KERN_SUCCESS) {
                    646:                vm_object_deallocate(vm_submap_object);
                    647:                return (kr);
                    648:        }
                    649: 
                    650:        pmap_reference(vm_map_pmap(parent));
                    651:        map = vm_map_create(vm_map_pmap(parent), *addr, *addr + size, pageable);
                    652:        if (map == VM_MAP_NULL)
                    653:                panic("kmem_suballoc: vm_map_create failed");   /* "can't happen" */
                    654: 
                    655:        kr = vm_map_submap(parent, *addr, *addr + size, map, *addr);
                    656:        if (kr != KERN_SUCCESS) {
                    657:                /*
                    658:                 * See comment preceding vm_map_submap().
                    659:                 */
                    660:                vm_map_remove(parent, *addr, *addr + size, VM_MAP_NO_FLAGS);
                    661:                vm_map_deallocate(map); /* also removes ref to pmap */
                    662:                vm_object_deallocate(vm_submap_object);
                    663:                return (kr);
                    664:        }
                    665: 
                    666:        *new_map = map;
                    667:        return (KERN_SUCCESS);
                    668: }
                    669: 
                    670: /*
                    671:  *     kmem_init:
                    672:  *
                    673:  *     Initialize the kernel's virtual memory map, taking
                    674:  *     into account all memory allocated up to this time.
                    675:  */
                    676: void
                    677: kmem_init(
                    678:        vm_offset_t     start,
                    679:        vm_offset_t     end)
                    680: {
                    681:        kernel_map = vm_map_create(pmap_kernel(),
                    682:                                   VM_MIN_KERNEL_ADDRESS, end,
                    683:                                   FALSE);
                    684: 
                    685:        /*
                    686:         *      Reserve virtual memory allocated up to this time.
                    687:         */
                    688: 
                    689:        if (start != VM_MIN_KERNEL_ADDRESS) {
                    690:                vm_offset_t addr = VM_MIN_KERNEL_ADDRESS;
                    691:                (void) vm_map_enter(kernel_map,
                    692:                                    &addr, start - VM_MIN_KERNEL_ADDRESS,
                    693:                                    (vm_offset_t) 0, TRUE,
                    694:                                    VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
                    695:                                    VM_PROT_DEFAULT, VM_PROT_ALL,
                    696:                                    VM_INHERIT_DEFAULT);
                    697:        }
                    698: 
                    699:         /*
                    700:          * Account for kernel memory (text, data, bss, vm shenanigans).
                    701:          * This may include inaccessible "holes" as determined by what
                    702:          * the machine-dependent init code includes in mem_size.
                    703:          */
                    704:         vm_page_wire_count = (atop(mem_size) - (vm_page_free_count
                    705:                                                 + vm_page_active_count
                    706:                                                 + vm_page_inactive_count));
                    707: }
                    708: 
                    709: /*
                    710:  *     kmem_io_map_copyout:
                    711:  *
                    712:  *     Establish temporary mapping in designated map for the memory
                    713:  *     passed in.  Memory format must be a page_list vm_map_copy.
                    714:  */
                    715: 
                    716: kern_return_t
                    717: kmem_io_map_copyout(
                    718:        vm_map_t        map,
                    719:        vm_offset_t     *addr,          /* actual addr of data */
                    720:        vm_size_t       *alloc_size,    /* size allocated */
                    721:        vm_map_copy_t   copy,
                    722:        vm_size_t       min_size,       /* Do at least this much */
                    723:        vm_prot_t       prot)           /* Protection of mapping */
                    724: {
                    725:        vm_offset_t     myaddr, offset;
                    726:        vm_size_t       mysize, copy_size;
                    727:        kern_return_t   ret;
                    728:        register
                    729:        vm_page_t       *page_list;
                    730:        vm_map_copy_t   new_copy;
                    731:        register
                    732:        int             i;
                    733: 
                    734:        assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                    735:        assert(min_size != 0);
                    736: 
                    737:        /*
                    738:         *      Figure out the size in vm pages.
                    739:         */
                    740:        min_size += copy->offset - trunc_page(copy->offset);
                    741:        min_size = round_page(min_size);
                    742:        mysize = round_page(copy->offset + copy->size) -
                    743:                trunc_page(copy->offset);
                    744: 
                    745:        /*
                    746:         *      If total size is larger than one page list and
                    747:         *      we don't have to do more than one page list, then
                    748:         *      only do one page list.  
                    749:         *
                    750:         * XXX  Could be much smarter about this ... like trimming length
                    751:         * XXX  if we need more than one page list but not all of them.
                    752:         */
                    753: 
                    754:        copy_size = ptoa(copy->cpy_npages);
                    755:        if (mysize > copy_size && copy_size > min_size)
                    756:                mysize = copy_size;
                    757: 
                    758:        /*
                    759:         *      Allocate some address space in the map (must be kernel
                    760:         *      space).
                    761:         */
                    762:        myaddr = vm_map_min(map);
                    763:        ret = vm_map_enter(map, &myaddr, mysize,
                    764:                          (vm_offset_t) 0, TRUE,
                    765:                          VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
                    766:                          prot, prot, VM_INHERIT_DEFAULT);
                    767: 
                    768:        if (ret != KERN_SUCCESS)
                    769:                return(ret);
                    770: 
                    771:        /*
                    772:         *      Tell the pmap module that this will be wired, and
                    773:         *      enter the mappings.
                    774:         */
                    775:        pmap_pageable(vm_map_pmap(map), myaddr, myaddr + mysize, TRUE);
                    776: 
                    777:        *addr = myaddr + (copy->offset - trunc_page(copy->offset));
                    778:        *alloc_size = mysize;
                    779: 
                    780:        offset = myaddr;
                    781:        page_list = &copy->cpy_page_list[0];
                    782:        while (TRUE) {
                    783:                for ( i = 0; i < copy->cpy_npages; i++, offset += PAGE_SIZE) {
                    784:                        PMAP_ENTER(vm_map_pmap(map), offset, *page_list,
                    785:                                   prot, TRUE);
                    786:                        page_list++;
                    787:                }
                    788: 
                    789:                if (offset == (myaddr + mysize))
                    790:                        break;
                    791: 
                    792:                /*
                    793:                 *      Onward to the next page_list.  The extend_cont
                    794:                 *      leaves the current page list's pages alone; 
                    795:                 *      they'll be cleaned up at discard.  Reset this
                    796:                 *      copy's continuation to discard the next one.
                    797:                 */
                    798:                vm_map_copy_invoke_extend_cont(copy, &new_copy, &ret);
                    799: 
                    800:                if (ret != KERN_SUCCESS) {
                    801:                        kmem_io_map_deallocate(map, myaddr, mysize);
                    802:                        return(ret);
                    803:                }
                    804:                copy->cpy_cont = vm_map_copy_discard_cont;
                    805:                copy->cpy_cont_args = (vm_map_copyin_args_t) new_copy;
                    806:                assert(new_copy != VM_MAP_COPY_NULL);
                    807:                assert(new_copy->type == VM_MAP_COPY_PAGE_LIST);
                    808:                copy = new_copy;
                    809:                page_list = &copy->cpy_page_list[0];
                    810:        }
                    811: 
                    812:        return(ret);
                    813: }
                    814: 
                    815: /*
                    816:  *     kmem_io_map_deallocate:
                    817:  *
                    818:  *     Get rid of the mapping established by kmem_io_map_copyout.
                    819:  *     Assumes that addr and size have been rounded to page boundaries.
                    820:  */
                    821: 
                    822: void
                    823: kmem_io_map_deallocate(
                    824:        vm_map_t        map,
                    825:        vm_offset_t     addr,
                    826:        vm_size_t       size)
                    827: {
                    828: 
                    829:        register vm_offset_t    va, end;
                    830: 
                    831:        end = round_page(addr + size);
                    832:        for (va = trunc_page(addr); va < end; va += PAGE_SIZE)
                    833:            pmap_change_wiring(vm_map_pmap(map), va, FALSE);
                    834: 
                    835:        /*
                    836:         *      Remove the mappings.  The pmap_remove is needed.
                    837:         */
                    838:        
                    839:        pmap_remove(vm_map_pmap(map), addr, addr + size);
                    840:        vm_map_remove(map, addr, addr + size, VM_MAP_REMOVE_KUNWIRE);
                    841: }
                    842: 
                    843: 
                    844: /*
                    845:  *     kmem_io_object_trunc:
                    846:  *
                    847:  *     Truncate an object vm_map_copy_t.
                    848:  *     Called by the scatter/gather list network code to remove pages from
                    849:  *     the tail end of a packet. Also unwires the objects pages.
                    850:  */
                    851: 
                    852: kern_return_t
                    853: kmem_io_object_trunc(copy, new_size)
                    854:      vm_map_copy_t     copy;           /* IN/OUT copy object */
                    855:      register vm_size_t new_size;      /* IN new object size */
                    856: {
                    857:        register vm_size_t      offset, old_size;
                    858: 
                    859:        assert(copy->type == VM_MAP_COPY_OBJECT);
                    860: 
                    861:        old_size = round_page(copy->size);
                    862:        copy->size = new_size;
                    863:        new_size = round_page(new_size);
                    864: 
                    865:         vm_object_lock(copy->cpy_object);
                    866:         vm_object_page_remove(copy->cpy_object,
                    867:                               (vm_offset_t)new_size, (vm_offset_t)old_size);
                    868:         for (offset = 0; offset < new_size; offset += PAGE_SIZE) {
                    869:                register vm_page_t      mem;
                    870: 
                    871:                if ((mem = vm_page_lookup(copy->cpy_object, offset)) == VM_PAGE_NULL)
                    872:                    panic("kmem_io_object_trunc: unable to find object page");
                    873: 
                    874:                /*
                    875:                 * Make sure these pages are marked dirty
                    876:                 */
                    877:                mem->dirty = TRUE;
                    878:                vm_page_lock_queues();
                    879:                vm_page_unwire(mem);
                    880:                vm_page_unlock_queues();
                    881:        }
                    882:         copy->cpy_object->size = new_size;     /*  adjust size of object */
                    883:         vm_object_unlock(copy->cpy_object);
                    884:         return(KERN_SUCCESS);
                    885: }
                    886: 
                    887: /*
                    888:  *     kmem_io_object_deallocate:
                    889:  *
                    890:  *     Free an vm_map_copy_t.
                    891:  *     Called by the scatter/gather list network code to free a packet.
                    892:  */
                    893: 
                    894: void
                    895: kmem_io_object_deallocate(
                    896:      vm_map_copy_t     copy)           /* IN/OUT copy object */
                    897: {
                    898:        kern_return_t   ret;
                    899: 
                    900:        /*
                    901:         * Clear out all the object pages (this will leave an empty object).
                    902:         */
                    903:        ret = kmem_io_object_trunc(copy, 0);
                    904:        if (ret != KERN_SUCCESS)
                    905:                panic("kmem_io_object_deallocate: unable to truncate object");
                    906:        /*
                    907:         * ...and discard the copy object.
                    908:         */
                    909:        vm_map_copy_discard(copy);
                    910: }
                    911: 
                    912: /*
                    913:  *     Routine:        copyinmap
                    914:  *     Purpose:
                    915:  *             Like copyin, except that fromaddr is an address
                    916:  *             in the specified VM map.  This implementation
                    917:  *             is incomplete; it handles the current user map
                    918:  *             and the kernel map/submaps.
                    919:  */
                    920: boolean_t
                    921: copyinmap(
                    922:        vm_map_t        map,
                    923:        vm_offset_t     fromaddr,
                    924:        vm_offset_t     toaddr,
                    925:        vm_size_t       length)
                    926: {
                    927:        if (vm_map_pmap(map) == pmap_kernel()) {
                    928:                /* assume a correct copy */
                    929:                memcpy((void *)toaddr, (void *)fromaddr, length);
                    930:                return FALSE;
                    931:        }
                    932: 
                    933:        if (current_map() == map)
                    934:                return copyin((char *)fromaddr, (char *)toaddr, length);
                    935: 
                    936:        return TRUE;
                    937: }
                    938: 
                    939: /*
                    940:  *     Routine:        copyoutmap
                    941:  *     Purpose:
                    942:  *             Like copyout, except that toaddr is an address
                    943:  *             in the specified VM map.  This implementation
                    944:  *             is incomplete; it handles the current user map
                    945:  *             and the kernel map/submaps.
                    946:  */
                    947: boolean_t
                    948: copyoutmap(
                    949:        vm_map_t        map,
                    950:        vm_offset_t     fromaddr,
                    951:        vm_offset_t     toaddr,
                    952:        vm_size_t       length)
                    953: {
                    954:        if (vm_map_pmap(map) == pmap_kernel()) {
                    955:                /* assume a correct copy */
                    956:                memcpy((void *)toaddr, (void *)fromaddr, length);
                    957:                return FALSE;
                    958:        }
                    959: 
                    960:        if (current_map() == map)
                    961:                return copyout((char *)fromaddr, (char *)toaddr, length);
                    962: 
                    963:        return TRUE;
                    964: }

unix.superglobalmegacorp.com

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