Annotation of XNU/osfmk/vm/vm_user.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 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_user.c
                     54:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     55:  * 
                     56:  *     User-exported virtual memory functions.
                     57:  */
                     58: #ifdef MACH_BSD
                     59: /* remove after component interface available */
                     60: extern int     vnode_pager_workaround;
                     61: #endif
                     62: 
                     63: #include <vm_cpm.h>
                     64: #include <mach/boolean.h>
                     65: #include <mach/kern_return.h>
                     66: #include <mach/mach_types.h>   /* to get vm_address_t */
                     67: #include <mach/memory_object.h>
                     68: #include <mach/std_types.h>    /* to get pointer_t */
                     69: #include <mach/vm_attributes.h>
                     70: #include <mach/vm_param.h>
                     71: #include <mach/vm_statistics.h>
                     72: #include <mach/vm_task_server.h>
                     73: #include <mach/mach_syscalls.h>
                     74: #include <mach/shared_memory_server.h>
                     75: 
                     76: #include <kern/host.h>
                     77: #include <kern/task.h>
                     78: #include <kern/misc_protos.h>
                     79: #include <vm/vm_map.h>
                     80: #include <vm/vm_object.h>
                     81: #include <vm/vm_page.h>
                     82: #include <vm/memory_object.h>
                     83: #include <vm/vm_pageout.h>
                     84: 
                     85: 
                     86: 
                     87: vm_size_t        upl_offset_to_pagelist = 0;
                     88: 
                     89: #if    VM_CPM
                     90: #include <vm/cpm.h>
                     91: #endif /* VM_CPM */
                     92: 
                     93: ipc_port_t     dynamic_pager_control_port=NULL;
                     94: 
                     95: /*
                     96:  *     vm_allocate allocates "zero fill" memory in the specfied
                     97:  *     map.
                     98:  */
                     99: kern_return_t
                    100: vm_allocate(
                    101:        register vm_map_t       map,
                    102:        register vm_offset_t    *addr,
                    103:        register vm_size_t      size,
                    104:        int                     flags)
                    105: {
                    106:        kern_return_t   result;
                    107:        boolean_t       anywhere = VM_FLAGS_ANYWHERE & flags;
                    108: 
                    109:        if (map == VM_MAP_NULL)
                    110:                return(KERN_INVALID_ARGUMENT);
                    111:        if (size == 0) {
                    112:                *addr = 0;
                    113:                return(KERN_SUCCESS);
                    114:        }
                    115: 
                    116:        if (anywhere)
                    117:                *addr = vm_map_min(map);
                    118:        else
                    119:                *addr = trunc_page(*addr);
                    120:        size = round_page(size);
                    121: 
                    122:        result = vm_map_enter(
                    123:                        map,
                    124:                        addr,
                    125:                        size,
                    126:                        (vm_offset_t)0,
                    127:                        flags,
                    128:                        VM_OBJECT_NULL,
                    129:                        (vm_offset_t)0,
                    130:                        FALSE,
                    131:                        VM_PROT_DEFAULT,
                    132:                        VM_PROT_ALL,
                    133:                        VM_INHERIT_DEFAULT);
                    134: 
                    135:        return(result);
                    136: }
                    137: 
                    138: /*
                    139:  *     vm_deallocate deallocates the specified range of addresses in the
                    140:  *     specified address map.
                    141:  */
                    142: kern_return_t
                    143: vm_deallocate(
                    144:        register vm_map_t       map,
                    145:        vm_offset_t             start,
                    146:        vm_size_t               size)
                    147: {
                    148:        if (map == VM_MAP_NULL)
                    149:                return(KERN_INVALID_ARGUMENT);
                    150: 
                    151:        if (size == (vm_offset_t) 0)
                    152:                return(KERN_SUCCESS);
                    153: 
                    154:        return(vm_map_remove(map, trunc_page(start),
                    155:                             round_page(start+size), VM_MAP_NO_FLAGS));
                    156: }
                    157: 
                    158: /*
                    159:  *     vm_inherit sets the inheritance of the specified range in the
                    160:  *     specified map.
                    161:  */
                    162: kern_return_t
                    163: vm_inherit(
                    164:        register vm_map_t       map,
                    165:        vm_offset_t             start,
                    166:        vm_size_t               size,
                    167:        vm_inherit_t            new_inheritance)
                    168: {
                    169:        if (map == VM_MAP_NULL)
                    170:                return(KERN_INVALID_ARGUMENT);
                    171: 
                    172:        if (new_inheritance > VM_INHERIT_LAST_VALID)
                    173:                 return(KERN_INVALID_ARGUMENT);
                    174: 
                    175:        return(vm_map_inherit(map,
                    176:                              trunc_page(start),
                    177:                              round_page(start+size),
                    178:                              new_inheritance));
                    179: }
                    180: 
                    181: /*
                    182:  *     vm_protect sets the protection of the specified range in the
                    183:  *     specified map.
                    184:  */
                    185: 
                    186: kern_return_t
                    187: vm_protect(
                    188:        register vm_map_t       map,
                    189:        vm_offset_t             start,
                    190:        vm_size_t               size,
                    191:        boolean_t               set_maximum,
                    192:        vm_prot_t               new_protection)
                    193: {
                    194:        if ((map == VM_MAP_NULL) || (new_protection & ~VM_PROT_ALL))
                    195:                return(KERN_INVALID_ARGUMENT);
                    196: 
                    197:        return(vm_map_protect(map,
                    198:                              trunc_page(start),
                    199:                              round_page(start+size),
                    200:                              new_protection,
                    201:                              set_maximum));
                    202: }
                    203: 
                    204: /*
                    205:  * Handle machine-specific attributes for a mapping, such
                    206:  * as cachability, migrability, etc.
                    207:  */
                    208: kern_return_t
                    209: vm_machine_attribute(
                    210:        vm_map_t        map,
                    211:        vm_address_t    address,
                    212:        vm_size_t       size,
                    213:        vm_machine_attribute_t  attribute,
                    214:        vm_machine_attribute_val_t* value)              /* IN/OUT */
                    215: {
                    216:        if (map == VM_MAP_NULL)
                    217:                return(KERN_INVALID_ARGUMENT);
                    218: 
                    219:        return vm_map_machine_attribute(map, address, size, attribute, value);
                    220: }
                    221: 
                    222: kern_return_t
                    223: vm_read(
                    224:        vm_map_t                map,
                    225:        vm_address_t            address,
                    226:        vm_size_t               size,
                    227:        pointer_t               *data,
                    228:        mach_msg_type_number_t  *data_size)
                    229: {
                    230:        kern_return_t   error;
                    231:        vm_map_copy_t   ipc_address;
                    232: 
                    233:        if (map == VM_MAP_NULL)
                    234:                return(KERN_INVALID_ARGUMENT);
                    235: 
                    236:        if ((error = vm_map_copyin(map,
                    237:                                address,
                    238:                                size,
                    239:                                FALSE,  /* src_destroy */
                    240:                                &ipc_address)) == KERN_SUCCESS) {
                    241:                *data = (pointer_t) ipc_address;
                    242:                *data_size = size;
                    243:        }
                    244:        return(error);
                    245: }
                    246: 
                    247: kern_return_t
                    248: vm_read_list(
                    249:        vm_map_t                map,
                    250:        vm_read_entry_t         data_list,
                    251:        mach_msg_type_number_t  count)
                    252: {
                    253:        mach_msg_type_number_t  i;
                    254:        kern_return_t   error;
                    255:        vm_map_copy_t   ipc_address;
                    256: 
                    257:        if (map == VM_MAP_NULL)
                    258:                return(KERN_INVALID_ARGUMENT);
                    259: 
                    260:        for(i=0; i<count; i++) {
                    261:                error = vm_map_copyin(map,
                    262:                                data_list[i].address,
                    263:                                data_list[i].size,
                    264:                                FALSE,  /* src_destroy */
                    265:                                &ipc_address);
                    266:                if(error != KERN_SUCCESS) {
                    267:                        data_list[i].address = (vm_address_t)0;
                    268:                        data_list[i].size = (vm_size_t)0;
                    269:                        break;
                    270:                }
                    271:                if(data_list[i].size != 0) {
                    272:                        error = vm_map_copyout(current_task()->map, 
                    273:                                                &(data_list[i].address),
                    274:                                                 (vm_map_copy_t) ipc_address);
                    275:                        if(error != KERN_SUCCESS) {
                    276:                                data_list[i].address = (vm_address_t)0;
                    277:                                data_list[i].size = (vm_size_t)0;
                    278:                                break;
                    279:                        }
                    280:                }
                    281:        }
                    282:        return(error);
                    283: }
                    284: 
                    285: /*
                    286:  * This routine reads from the specified map and overwrites part of the current
                    287:  * activation's map.  In making an assumption that the current thread is local,
                    288:  * it is no longer cluster-safe without a fully supportive local proxy thread/
                    289:  * task (but we don't support cluster's anymore so this is moot).
                    290:  */
                    291: 
                    292: #define VM_OVERWRITE_SMALL 512
                    293: 
                    294: kern_return_t
                    295: vm_read_overwrite(
                    296:                  vm_map_t      map,
                    297:                  vm_address_t  address,
                    298:                  vm_size_t     size,
                    299:                  vm_address_t  data,
                    300:                  vm_size_t     *data_size)
                    301: {
                    302:        struct {
                    303:            long        align;
                    304:            char        buf[VM_OVERWRITE_SMALL];
                    305:        } inbuf;
                    306:        vm_map_t        oldmap;
                    307:        kern_return_t   error = KERN_SUCCESS;
                    308:        vm_map_copy_t   copy;
                    309: 
                    310:        if (map == VM_MAP_NULL)
                    311:                return(KERN_INVALID_ARGUMENT);
                    312: 
                    313:        if (size <= VM_OVERWRITE_SMALL) {
                    314:                if(vm_map_read_user(map, (vm_offset_t)address, 
                    315:                                        (vm_offset_t)&inbuf, size)) {
                    316:                        error = KERN_INVALID_ADDRESS;
                    317:                } else {
                    318:                        if(vm_map_write_user(current_map(), 
                    319:                                (vm_offset_t)&inbuf, (vm_offset_t)data, size))
                    320:                        error = KERN_INVALID_ADDRESS;
                    321:                }
                    322:        }
                    323:        else {
                    324:                if ((error = vm_map_copyin(map,
                    325:                                        address,
                    326:                                        size,
                    327:                                        FALSE,  /* src_destroy */
                    328:                                        &copy)) == KERN_SUCCESS) {
                    329:                        if ((error = vm_map_copy_overwrite(
                    330:                                        current_act()->map,
                    331:                                        data, 
                    332:                                        copy,
                    333:                                        FALSE)) == KERN_SUCCESS) {
                    334:                        }
                    335:                        else {
                    336:                                vm_map_copy_discard(copy);
                    337:                        }
                    338:                }
                    339:        }
                    340:        *data_size = size;
                    341:        return(error);
                    342: }
                    343: 
                    344: 
                    345: 
                    346: 
                    347: /*ARGSUSED*/
                    348: kern_return_t
                    349: vm_write(
                    350:        vm_map_t                map,
                    351:        vm_address_t            address,
                    352:        vm_offset_t             data,
                    353:        mach_msg_type_number_t  size)
                    354: {
                    355:        if (map == VM_MAP_NULL)
                    356:                return KERN_INVALID_ARGUMENT;
                    357: 
                    358:        return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data,
                    359:                                     FALSE /* interruptible XXX */);
                    360: }
                    361: 
                    362: kern_return_t
                    363: vm_copy(
                    364:        vm_map_t        map,
                    365:        vm_address_t    source_address,
                    366:        vm_size_t       size,
                    367:        vm_address_t    dest_address)
                    368: {
                    369:        vm_map_copy_t copy;
                    370:        kern_return_t kr;
                    371: 
                    372:        if (map == VM_MAP_NULL)
                    373:                return KERN_INVALID_ARGUMENT;
                    374: 
                    375:        kr = vm_map_copyin(map, source_address, size,
                    376:                           FALSE, &copy);
                    377:        if (kr != KERN_SUCCESS)
                    378:                return kr;
                    379: 
                    380:        kr = vm_map_copy_overwrite(map, dest_address, copy,
                    381:                                   FALSE /* interruptible XXX */);
                    382:        if (kr != KERN_SUCCESS) {
                    383:                vm_map_copy_discard(copy);
                    384:                return kr;
                    385:        }
                    386: 
                    387:        return KERN_SUCCESS;
                    388: }
                    389: 
                    390: /*
                    391:  *     Routine:        vm_map
                    392:  */
                    393: kern_return_t
                    394: vm_map(
                    395:        vm_map_t        target_map,
                    396:        vm_offset_t     *address,
                    397:        vm_size_t       size,
                    398:        vm_offset_t     mask,
                    399:        int             flags,
                    400:        ipc_port_t      port,
                    401:        vm_offset_t     offset,
                    402:        boolean_t       copy,
                    403:        vm_prot_t       cur_protection,
                    404:        vm_prot_t       max_protection,
                    405:        vm_inherit_t    inheritance)
                    406: {
                    407:        register
                    408:        vm_object_t     object;
                    409:        vm_prot_t       prot;
                    410:        kern_return_t   result;
                    411: 
                    412:        /*
                    413:         * Check arguments for validity
                    414:         */
                    415:        if ((target_map == VM_MAP_NULL) ||
                    416:                (cur_protection & ~VM_PROT_ALL) ||
                    417:                (max_protection & ~VM_PROT_ALL) ||
                    418:                (inheritance > VM_INHERIT_LAST_VALID) ||
                    419:                size == 0)
                    420:                return(KERN_INVALID_ARGUMENT);
                    421: 
                    422:        /*
                    423:         * Find the vm object (if any) corresponding to this port.
                    424:         */
                    425:        if (!IP_VALID(port)) {
                    426:                object = VM_OBJECT_NULL;
                    427:                offset = 0;
                    428:                copy = FALSE;
                    429:        } else if (ip_kotype(port) == IKOT_NAMED_ENTRY) {
                    430:                vm_named_entry_t        named_entry;
                    431: 
                    432:                named_entry = (vm_named_entry_t)port->ip_kobject;
                    433:                /* a few checks to make sure user is obeying rules */
                    434:                if(size == 0)
                    435:                        size = named_entry->size;
                    436:                if((named_entry->protection & max_protection) != max_protection)
                    437:                        return(KERN_INVALID_RIGHT);
                    438:                if((named_entry->protection & cur_protection) != cur_protection)
                    439:                        return(KERN_INVALID_RIGHT);
                    440:                if(named_entry->size < (offset + size))
                    441:                        return(KERN_INVALID_ARGUMENT);
                    442: 
                    443:                /* the callers parameter offset is defined to be the */
                    444:                /* offset from beginning of named entry offset in object */
                    445:                offset = offset + named_entry->offset;
                    446:                
                    447:                named_entry_lock(named_entry);
                    448:                if(named_entry->is_sub_map) {
                    449:                        vm_map_entry_t          map_entry;
                    450: 
                    451:                        named_entry_unlock(named_entry);
                    452:                        *address = trunc_page(*address);
                    453:                        size = round_page(size);
                    454:                        vm_object_reference(vm_submap_object);
                    455:                        if ((result = vm_map_enter(target_map,
                    456:                                address, size, mask, flags,
                    457:                                vm_submap_object, 0,
                    458:                                FALSE,
                    459:                                cur_protection, max_protection, inheritance
                    460:                                )) != KERN_SUCCESS) {
                    461:                                        vm_object_deallocate(vm_submap_object);
                    462:                        } else {
                    463:                                vm_map_submap(target_map, *address, 
                    464:                                        (*address) + size, 
                    465:                                        named_entry->backing.map,
                    466:                                        offset);
                    467:                                if(copy) {
                    468:                                        if(vm_map_lookup_entry(
                    469:                                           target_map, *address, &map_entry)) {
                    470:                                                map_entry->needs_copy = TRUE;
                    471:                                        }
                    472:                                }
                    473:                        }
                    474:                        return(result);
                    475: 
                    476:                } else if(named_entry->object) {
                    477:                        /* This is the case where we are going to map */
                    478:                        /* an already mapped object.  If the object is */
                    479:                        /* not ready it is internal.  An external     */
                    480:                        /* object cannot be mapped until it is ready  */
                    481:                        /* we can therefore avoid the ready check     */
                    482:                        /* in this case.  */
                    483:                        copy = FALSE;
                    484:                        named_entry_unlock(named_entry);
                    485:                        vm_object_reference(named_entry->object);
                    486:                        object = named_entry->object;
                    487:                } else {
                    488:                        object = vm_object_enter(named_entry->backing.pager, 
                    489:                                        named_entry->size, 
                    490:                                        named_entry->internal, 
                    491:                                        FALSE);
                    492:                        if (object == VM_OBJECT_NULL) {
                    493:                                named_entry_unlock(named_entry);
                    494:                                return(KERN_INVALID_OBJECT);
                    495:                        }
                    496:                        named_entry->object = object;
                    497:                        named_entry_unlock(named_entry);
                    498:                        /* create an extra reference for the named entry */
                    499:                        vm_object_reference(named_entry->object);
                    500:                        /* wait for object (if any) to be ready */
                    501:                        if (object != VM_OBJECT_NULL) {
                    502:                                vm_object_lock(object);
                    503:                                while (!object->pager_ready) {
                    504:                                        vm_object_wait(object,
                    505:                                                VM_OBJECT_EVENT_PAGER_READY,
                    506:                                                THREAD_UNINT);
                    507:                                        vm_object_lock(object);
                    508:                                }
                    509:                                vm_object_unlock(object);
                    510:                        }
                    511:                }
                    512:        } else {
                    513:                if ((object = vm_object_enter(port, size, FALSE, FALSE))
                    514:                        == VM_OBJECT_NULL)
                    515:                        return(KERN_INVALID_OBJECT);
                    516: 
                    517:                /* wait for object (if any) to be ready */
                    518:                if (object != VM_OBJECT_NULL) {
                    519:                        vm_object_lock(object);
                    520:                        while (!object->pager_ready) {
                    521:                                vm_object_wait(object,
                    522:                                        VM_OBJECT_EVENT_PAGER_READY,
                    523:                                        THREAD_UNINT);
                    524:                                vm_object_lock(object);
                    525:                        }
                    526:                        vm_object_unlock(object);
                    527:                }
                    528:        }
                    529: 
                    530:        *address = trunc_page(*address);
                    531:        size = round_page(size);
                    532: 
                    533:        /*
                    534:         *      Perform the copy if requested
                    535:         */
                    536: 
                    537:        if (copy) {
                    538:                vm_object_t     new_object;
                    539:                vm_offset_t     new_offset;
                    540: 
                    541:                result = vm_object_copy_strategically(object, offset, size,
                    542:                                &new_object, &new_offset,
                    543:                                &copy);
                    544: 
                    545: 
                    546:                if (result == KERN_MEMORY_RESTART_COPY) {
                    547:                        boolean_t success;
                    548:                        boolean_t src_needs_copy;
                    549: 
                    550:                        /*
                    551:                         * XXX
                    552:                         * We currently ignore src_needs_copy.
                    553:                         * This really is the issue of how to make
                    554:                         * MEMORY_OBJECT_COPY_SYMMETRIC safe for
                    555:                         * non-kernel users to use. Solution forthcoming.
                    556:                         * In the meantime, since we don't allow non-kernel
                    557:                         * memory managers to specify symmetric copy,
                    558:                         * we won't run into problems here.
                    559:                         */
                    560:                        new_object = object;
                    561:                        new_offset = offset;
                    562:                        success = vm_object_copy_quickly(&new_object,
                    563:                                                         new_offset, size,
                    564:                                                         &src_needs_copy,
                    565:                                                         &copy);
                    566:                        assert(success);
                    567:                        result = KERN_SUCCESS;
                    568:                }
                    569:                /*
                    570:                 *      Throw away the reference to the
                    571:                 *      original object, as it won't be mapped.
                    572:                 */
                    573: 
                    574:                vm_object_deallocate(object);
                    575: 
                    576:                if (result != KERN_SUCCESS)
                    577:                        return (result);
                    578: 
                    579:                object = new_object;
                    580:                offset = new_offset;
                    581:        }
                    582: 
                    583:        if ((result = vm_map_enter(target_map,
                    584:                                address, size, mask, flags,
                    585:                                object, offset,
                    586:                                copy,
                    587:                                cur_protection, max_protection, inheritance
                    588:                                )) != KERN_SUCCESS)
                    589:        vm_object_deallocate(object);
                    590:        return(result);
                    591: }
                    592: 
                    593: 
                    594: /*
                    595:  * NOTE: this routine (and this file) will no longer require mach_host_server.h
                    596:  * when vm_wire is changed to use ledgers.
                    597:  */
                    598: #include <mach/mach_host_server.h>
                    599: /*
                    600:  *     Specify that the range of the virtual address space
                    601:  *     of the target task must not cause page faults for
                    602:  *     the indicated accesses.
                    603:  *
                    604:  *     [ To unwire the pages, specify VM_PROT_NONE. ]
                    605:  */
                    606: kern_return_t
                    607: vm_wire(
                    608:        host_t                  host,
                    609:        register vm_map_t       map,
                    610:        vm_offset_t             start,
                    611:        vm_size_t               size,
                    612:        vm_prot_t               access)
                    613: {
                    614:        kern_return_t           rc;
                    615: 
                    616:        if (host == HOST_NULL)
                    617:                return KERN_INVALID_HOST;
                    618: 
                    619:        if (map == VM_MAP_NULL)
                    620:                return KERN_INVALID_TASK;
                    621: 
                    622:        if (access & ~VM_PROT_ALL)
                    623:                return KERN_INVALID_ARGUMENT;
                    624: 
                    625:        if (access != VM_PROT_NONE) {
                    626:                rc = vm_map_wire(map, trunc_page(start),
                    627:                                 round_page(start+size), access, TRUE);
                    628:        } else {
                    629:                rc = vm_map_unwire(map, trunc_page(start),
                    630:                                   round_page(start+size), TRUE);
                    631:        }
                    632:        return rc;
                    633: }
                    634: 
                    635: /*
                    636:  *     vm_msync
                    637:  *
                    638:  *     Synchronises the memory range specified with its backing store
                    639:  *     image by either flushing or cleaning the contents to the appropriate
                    640:  *     memory manager engaging in a memory object synchronize dialog with
                    641:  *     the manager.  The client doesn't return until the manager issues
                    642:  *     m_o_s_completed message.  MIG Magically converts user task parameter
                    643:  *     to the task's address map.
                    644:  *
                    645:  *     interpretation of sync_flags
                    646:  *     VM_SYNC_INVALIDATE      - discard pages, only return precious
                    647:  *                               pages to manager.
                    648:  *
                    649:  *     VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
                    650:  *                             - discard pages, write dirty or precious
                    651:  *                               pages back to memory manager.
                    652:  *
                    653:  *     VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
                    654:  *                             - write dirty or precious pages back to
                    655:  *                               the memory manager.
                    656:  *
                    657:  *     NOTE
                    658:  *     The memory object attributes have not yet been implemented, this
                    659:  *     function will have to deal with the invalidate attribute
                    660:  *
                    661:  *     RETURNS
                    662:  *     KERN_INVALID_TASK               Bad task parameter
                    663:  *     KERN_INVALID_ARGUMENT           both sync and async were specified.
                    664:  *     KERN_SUCCESS                    The usual.
                    665:  */
                    666: 
                    667: kern_return_t
                    668: vm_msync(
                    669:        vm_map_t        map,
                    670:        vm_address_t    address,
                    671:        vm_size_t       size,
                    672:        vm_sync_t       sync_flags)
                    673: {
                    674:        msync_req_t             msr;
                    675:        msync_req_t             new_msr;
                    676:        queue_chain_t           req_q;  /* queue of requests for this msync */
                    677:        vm_map_entry_t          entry;
                    678:        vm_size_t               amount_left;
                    679:        vm_offset_t             offset;
                    680:        boolean_t               do_sync_req;
                    681:        boolean_t               modifiable;
                    682:        
                    683: 
                    684:        if ((sync_flags & VM_SYNC_ASYNCHRONOUS) &&
                    685:            (sync_flags & VM_SYNC_SYNCHRONOUS))
                    686:                return(KERN_INVALID_ARGUMENT);
                    687: 
                    688:        /*
                    689:         * align address and size on page boundaries
                    690:         */
                    691:        size = round_page(address + size) - trunc_page(address);
                    692:        address = trunc_page(address);
                    693: 
                    694:         if (map == VM_MAP_NULL)
                    695:                 return(KERN_INVALID_TASK);
                    696: 
                    697:        if (size == 0)
                    698:                return(KERN_SUCCESS);
                    699: 
                    700:        queue_init(&req_q);
                    701:        amount_left = size;
                    702: 
                    703:        while (amount_left > 0) {
                    704:                vm_size_t               flush_size;
                    705:                vm_object_t             object;
                    706: 
                    707:                vm_map_lock(map);
                    708:                if (!vm_map_lookup_entry(map, address, &entry)) {
                    709:                        vm_size_t       skip;
                    710: 
                    711:                        /*
                    712:                         * hole in the address map.
                    713:                         */
                    714: 
                    715:                        /*
                    716:                         * Check for empty map.
                    717:                         */
                    718:                        if (entry == vm_map_to_entry(map) &&
                    719:                            entry->vme_next == entry) {
                    720:                                vm_map_unlock(map);
                    721:                                break;
                    722:                        }
                    723:                        /*
                    724:                         * Check that we don't wrap and that
                    725:                         * we have at least one real map entry.
                    726:                         */
                    727:                        if ((map->hdr.nentries == 0) ||
                    728:                            (entry->vme_next->vme_start < address)) {
                    729:                                vm_map_unlock(map);
                    730:                                break;
                    731:                        }
                    732:                        /*
                    733:                         * Move up to the next entry if needed
                    734:                         */
                    735:                        skip = (entry->vme_next->vme_start - address);
                    736:                        if (skip >= amount_left)
                    737:                                amount_left = 0;
                    738:                        else
                    739:                                amount_left -= skip;
                    740:                        address = entry->vme_next->vme_start;
                    741:                        vm_map_unlock(map);
                    742:                        continue;
                    743:                }
                    744: 
                    745:                offset = address - entry->vme_start;
                    746: 
                    747:                /*
                    748:                 * do we have more to flush than is contained in this
                    749:                 * entry ?
                    750:                 */
                    751:                if (amount_left + entry->vme_start + offset > entry->vme_end) {
                    752:                        flush_size = entry->vme_end -
                    753:                                                 (entry->vme_start + offset);
                    754:                } else {
                    755:                        flush_size = amount_left;
                    756:                }
                    757:                amount_left -= flush_size;
                    758:                address += flush_size;
                    759: 
                    760:                object = entry->object.vm_object;
                    761: 
                    762:                /*
                    763:                 * We can't sync this object if the object has not been
                    764:                 * created yet
                    765:                 */
                    766:                if (object == VM_OBJECT_NULL) {
                    767:                        vm_map_unlock(map);
                    768:                        continue;
                    769:                }
                    770:                offset += entry->offset;
                    771:                modifiable = (entry->protection & VM_PROT_WRITE)
                    772:                                != VM_PROT_NONE;
                    773: 
                    774:                 vm_object_lock(object);
                    775: 
                    776:                if (sync_flags & VM_SYNC_KILLPAGES) {
                    777:                        if (object->ref_count == 1 && !object->shadow && !entry->needs_copy)
                    778:                                memory_object_kill_pages(object, offset, flush_size);
                    779: 
                    780:                        vm_object_unlock(object);
                    781:                        vm_map_unlock(map);
                    782:                        continue;
                    783:                }
                    784:                /*
                    785:                 * We can't sync this object if there isn't a pager.
                    786:                 * Don't bother to sync internal objects, since there can't
                    787:                 * be any "permanent" storage for these objects anyway.
                    788:                 */
                    789:                if ((object->pager == IP_NULL) || (object->internal) ||
                    790:                    (object->private)) {
                    791:                        vm_object_unlock(object);
                    792:                        vm_map_unlock(map);
                    793:                        continue;
                    794:                }
                    795:                /*
                    796:                 * keep reference on the object until syncing is done
                    797:                 */
                    798:                assert(object->ref_count > 0);
                    799:                object->ref_count++;
                    800:                vm_object_res_reference(object);
                    801:                vm_object_unlock(object);
                    802: 
                    803:                vm_map_unlock(map);
                    804: 
                    805:                do_sync_req = memory_object_sync(object,
                    806:                                        offset,
                    807:                                        flush_size,
                    808:                                        sync_flags & VM_SYNC_INVALIDATE,
                    809:                                        (modifiable &&
                    810:                                        (sync_flags & VM_SYNC_SYNCHRONOUS ||
                    811:                                         sync_flags & VM_SYNC_ASYNCHRONOUS)));
                    812: 
                    813:                /*
                    814:                 * only send a m_o_s if we returned pages or if the entry
                    815:                 * is writable (ie dirty pages may have already been sent back)
                    816:                 */
                    817:                if (!do_sync_req && !modifiable) {
                    818:                        vm_object_deallocate(object);
                    819:                        continue;
                    820:                }
                    821:                msync_req_alloc(new_msr);
                    822: 
                    823:                 vm_object_lock(object);
                    824:                offset += object->paging_offset;
                    825: 
                    826:                new_msr->offset = offset;
                    827:                new_msr->length = flush_size;
                    828:                new_msr->object = object;
                    829:                new_msr->flag = VM_MSYNC_SYNCHRONIZING;
                    830: re_iterate:
                    831:                queue_iterate(&object->msr_q, msr, msync_req_t, msr_q) {
                    832:                        /*
                    833:                         * need to check for overlapping entry, if found, wait
                    834:                         * on overlapping msr to be done, then reiterate
                    835:                         */
                    836:                        msr_lock(msr);
                    837:                        if (msr->flag == VM_MSYNC_SYNCHRONIZING &&
                    838:                            ((offset >= msr->offset && 
                    839:                              offset < (msr->offset + msr->length)) ||
                    840:                             (msr->offset >= offset &&
                    841:                              msr->offset < (offset + flush_size))))
                    842:                        {
                    843:                                assert_wait((event_t) msr,THREAD_INTERRUPTIBLE);
                    844:                                msr_unlock(msr);
                    845:                                vm_object_unlock(object);
                    846:                                thread_block((void (*)(void))0);
                    847:                                if (current_act()->handlers)
                    848:                                        act_execute_returnhandlers();
                    849:                                vm_object_lock(object);
                    850:                                goto re_iterate;
                    851:                        }
                    852:                        msr_unlock(msr);
                    853:                }/* queue_iterate */
                    854: 
                    855:                queue_enter(&object->msr_q, new_msr, msync_req_t, msr_q);
                    856:                vm_object_unlock(object);
                    857: 
                    858:                queue_enter(&req_q, new_msr, msync_req_t, req_q);
                    859: 
                    860: #ifdef MACH_BSD
                    861:                if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) ==
                    862:                ((rpc_subsystem_t) &vnode_pager_workaround)) {
                    863:                        (void) vnode_pager_synchronize(
                    864:                                object->pager,
                    865:                                object->pager_request,
                    866:                                offset,
                    867:                                flush_size,
                    868:                                sync_flags);
                    869:                } else {
                    870:                        (void) memory_object_synchronize(
                    871:                                object->pager,
                    872:                                object->pager_request,
                    873:                                offset,
                    874:                                flush_size,
                    875:                                sync_flags);
                    876:                }
                    877: #else
                    878:                (void) memory_object_synchronize(
                    879:                                object->pager,
                    880:                                object->pager_request,
                    881:                                offset,
                    882:                                flush_size,
                    883:                                sync_flags);
                    884: #endif
                    885:        }/* while */
                    886: 
                    887:        /*
                    888:         * wait for memory_object_sychronize_completed messages from pager(s)
                    889:         */
                    890: 
                    891:        while (!queue_empty(&req_q)) {
                    892:                msr = (msync_req_t)queue_first(&req_q);
                    893:                msr_lock(msr);
                    894:                while(msr->flag != VM_MSYNC_DONE) {
                    895:                        assert_wait((event_t) msr, THREAD_INTERRUPTIBLE);
                    896:                        msr_unlock(msr);
                    897:                        thread_block((void (*)(void))0);
                    898:                        if (current_act()->handlers)
                    899:                                act_execute_returnhandlers();
                    900:                        msr_lock(msr);
                    901:                }/* while */
                    902:                queue_remove(&req_q, msr, msync_req_t, req_q);
                    903:                msr_unlock(msr);
                    904:                vm_object_deallocate(msr->object);
                    905:                msync_req_free(msr);
                    906:        }/* queue_iterate */
                    907: 
                    908:        return(KERN_SUCCESS);
                    909: }/* vm_msync */
                    910: 
                    911: 
                    912: /*
                    913:  *     task_wire
                    914:  *
                    915:  *     Set or clear the map's wiring_required flag.  This flag, if set,
                    916:  *     will cause all future virtual memory allocation to allocate
                    917:  *     user wired memory.  Unwiring pages wired down as a result of
                    918:  *     this routine is done with the vm_wire interface.
                    919:  */
                    920: kern_return_t
                    921: task_wire(
                    922:        vm_map_t        map,
                    923:        boolean_t       must_wire)
                    924: {
                    925:        if (map == VM_MAP_NULL)
                    926:                return(KERN_INVALID_ARGUMENT);
                    927: 
                    928:        if (must_wire)
                    929:                map->wiring_required = TRUE;
                    930:        else
                    931:                map->wiring_required = FALSE;
                    932: 
                    933:        return(KERN_SUCCESS);
                    934: }
                    935: 
                    936: /*
                    937:  *     vm_behavior_set sets the paging behavior attribute for the 
                    938:  *     specified range in the specified map. This routine will fail
                    939:  *     with KERN_INVALID_ADDRESS if any address in [start,start+size)
                    940:  *     is not a valid allocated or reserved memory region.
                    941:  */
                    942: kern_return_t 
                    943: vm_behavior_set(
                    944:        vm_map_t                map,
                    945:        vm_offset_t             start,
                    946:        vm_size_t               size,
                    947:        vm_behavior_t           new_behavior)
                    948: {
                    949:        if (map == VM_MAP_NULL)
                    950:                return(KERN_INVALID_ARGUMENT);
                    951: 
                    952:        return(vm_map_behavior_set(map, trunc_page(start), 
                    953:                                   round_page(start+size), new_behavior));
                    954: }
                    955: 
                    956: #if    VM_CPM
                    957: /*
                    958:  *     Control whether the kernel will permit use of
                    959:  *     vm_allocate_cpm at all.
                    960:  */
                    961: unsigned int   vm_allocate_cpm_enabled = 1;
                    962: 
                    963: /*
                    964:  *     Ordinarily, the right to allocate CPM is restricted
                    965:  *     to privileged applications (those that can gain access
                    966:  *     to the host port).  Set this variable to zero if you
                    967:  *     want to let any application allocate CPM.
                    968:  */
                    969: unsigned int   vm_allocate_cpm_privileged = 0;
                    970: 
                    971: /*
                    972:  *     Allocate memory in the specified map, with the caveat that
                    973:  *     the memory is physically contiguous.  This call may fail
                    974:  *     if the system can't find sufficient contiguous memory.
                    975:  *     This call may cause or lead to heart-stopping amounts of
                    976:  *     paging activity.
                    977:  *
                    978:  *     Memory obtained from this call should be freed in the
                    979:  *     normal way, viz., via vm_deallocate.
                    980:  */
                    981: kern_return_t
                    982: vm_allocate_cpm(
                    983:        host_t                  host,
                    984:        register vm_map_t       map,
                    985:        register vm_offset_t    *addr,
                    986:        register vm_size_t      size,
                    987:        int                     flags)
                    988: {
                    989:        vm_object_t             cpm_obj;
                    990:        pmap_t                  pmap;
                    991:        vm_page_t               m, pages;
                    992:        kern_return_t           kr;
                    993:        vm_offset_t             va, start, end, offset;
                    994: #if    MACH_ASSERT
                    995:        extern vm_offset_t      avail_start, avail_end;
                    996:        vm_offset_t             prev_addr;
                    997: #endif /* MACH_ASSERT */
                    998: 
                    999:        boolean_t               anywhere = VM_FLAGS_ANYWHERE & flags;
                   1000: 
                   1001:        if (!vm_allocate_cpm_enabled)
                   1002:                return KERN_FAILURE;
                   1003: 
                   1004:        if (vm_allocate_cpm_privileged && host == HOST_NULL)
                   1005:                return KERN_INVALID_HOST;
                   1006: 
                   1007:        if (map == VM_MAP_NULL)
                   1008:                return KERN_INVALID_ARGUMENT;
                   1009:        
                   1010:        if (size == 0) {
                   1011:                *addr = 0;
                   1012:                return KERN_SUCCESS;
                   1013:        }
                   1014: 
                   1015:        if (anywhere)
                   1016:                *addr = vm_map_min(map);
                   1017:        else
                   1018:                *addr = trunc_page(*addr);
                   1019:        size = round_page(size);
                   1020: 
                   1021:        if ((kr = cpm_allocate(size, &pages, TRUE)) != KERN_SUCCESS)
                   1022:                return kr;
                   1023: 
                   1024:        cpm_obj = vm_object_allocate(size);
                   1025:        assert(cpm_obj != VM_OBJECT_NULL);
                   1026:        assert(cpm_obj->internal);
                   1027:        assert(cpm_obj->size == size);
                   1028:        assert(cpm_obj->can_persist == FALSE);
                   1029:        assert(cpm_obj->pager_created == FALSE);
                   1030:        assert(cpm_obj->pageout == FALSE);
                   1031:        assert(cpm_obj->shadow == VM_OBJECT_NULL);
                   1032: 
                   1033:        /*
                   1034:         *      Insert pages into object.
                   1035:         */
                   1036: 
                   1037:        vm_object_lock(cpm_obj);
                   1038:        for (offset = 0; offset < size; offset += PAGE_SIZE) {
                   1039:                m = pages;
                   1040:                pages = NEXT_PAGE(m);
                   1041: 
                   1042:                assert(!m->gobbled);
                   1043:                assert(!m->wanted);
                   1044:                assert(!m->pageout);
                   1045:                assert(!m->tabled);
                   1046:                assert(m->busy);
                   1047:                assert(m->phys_addr>=avail_start && m->phys_addr<=avail_end);
                   1048: 
                   1049:                m->busy = FALSE;
                   1050:                vm_page_insert(m, cpm_obj, offset);
                   1051:        }
                   1052:        assert(cpm_obj->resident_page_count == size / PAGE_SIZE);
                   1053:        vm_object_unlock(cpm_obj);
                   1054: 
                   1055:        /*
                   1056:         *      Hang onto a reference on the object in case a
                   1057:         *      multi-threaded application for some reason decides
                   1058:         *      to deallocate the portion of the address space into
                   1059:         *      which we will insert this object.
                   1060:         *
                   1061:         *      Unfortunately, we must insert the object now before
                   1062:         *      we can talk to the pmap module about which addresses
                   1063:         *      must be wired down.  Hence, the race with a multi-
                   1064:         *      threaded app.
                   1065:         */
                   1066:        vm_object_reference(cpm_obj);
                   1067: 
                   1068:        /*
                   1069:         *      Insert object into map.
                   1070:         */
                   1071: 
                   1072:        kr = vm_map_enter(
                   1073:                          map,
                   1074:                          addr,
                   1075:                          size,
                   1076:                          (vm_offset_t)0,
                   1077:                          flags,
                   1078:                          cpm_obj,
                   1079:                          (vm_offset_t)0,
                   1080:                          FALSE,
                   1081:                          VM_PROT_ALL,
                   1082:                          VM_PROT_ALL,
                   1083:                          VM_INHERIT_DEFAULT);
                   1084: 
                   1085:        if (kr != KERN_SUCCESS) {
                   1086:                /*
                   1087:                 *      A CPM object doesn't have can_persist set,
                   1088:                 *      so all we have to do is deallocate it to
                   1089:                 *      free up these pages.
                   1090:                 */
                   1091:                assert(cpm_obj->pager_created == FALSE);
                   1092:                assert(cpm_obj->can_persist == FALSE);
                   1093:                assert(cpm_obj->pageout == FALSE);
                   1094:                assert(cpm_obj->shadow == VM_OBJECT_NULL);
                   1095:                vm_object_deallocate(cpm_obj); /* kill acquired ref */
                   1096:                vm_object_deallocate(cpm_obj); /* kill creation ref */
                   1097:        }
                   1098: 
                   1099:        /*
                   1100:         *      Inform the physical mapping system that the
                   1101:         *      range of addresses may not fault, so that
                   1102:         *      page tables and such can be locked down as well.
                   1103:         */
                   1104:        start = *addr;
                   1105:        end = start + size;
                   1106:        pmap = vm_map_pmap(map);
                   1107:        pmap_pageable(pmap, start, end, FALSE);
                   1108: 
                   1109:        /*
                   1110:         *      Enter each page into the pmap, to avoid faults.
                   1111:         *      Note that this loop could be coded more efficiently,
                   1112:         *      if the need arose, rather than looking up each page
                   1113:         *      again.
                   1114:         */
                   1115:        for (offset = 0, va = start; offset < size;
                   1116:             va += PAGE_SIZE, offset += PAGE_SIZE) {
                   1117:                vm_object_lock(cpm_obj);
                   1118:                m = vm_page_lookup(cpm_obj, offset);
                   1119:                vm_object_unlock(cpm_obj);
                   1120:                assert(m != VM_PAGE_NULL);
                   1121:                PMAP_ENTER(pmap, va, m, VM_PROT_ALL, TRUE);
                   1122:        }
                   1123: 
                   1124: #if    MACH_ASSERT
                   1125:        /*
                   1126:         *      Verify ordering in address space.
                   1127:         */
                   1128:        for (offset = 0; offset < size; offset += PAGE_SIZE) {
                   1129:                vm_object_lock(cpm_obj);
                   1130:                m = vm_page_lookup(cpm_obj, offset);
                   1131:                vm_object_unlock(cpm_obj);
                   1132:                if (m == VM_PAGE_NULL)
                   1133:                        panic("vm_allocate_cpm:  obj 0x%x off 0x%x no page",
                   1134:                              cpm_obj, offset);
                   1135:                assert(m->tabled);
                   1136:                assert(!m->busy);
                   1137:                assert(!m->wanted);
                   1138:                assert(!m->fictitious);
                   1139:                assert(!m->private);
                   1140:                assert(!m->absent);
                   1141:                assert(!m->error);
                   1142:                assert(!m->cleaning);
                   1143:                assert(!m->precious);
                   1144:                assert(!m->clustered);
                   1145:                if (offset != 0) {
                   1146:                        if (m->phys_addr != prev_addr + PAGE_SIZE) {
                   1147:                                printf("start 0x%x end 0x%x va 0x%x\n",
                   1148:                                       start, end, va);
                   1149:                                printf("obj 0x%x off 0x%x\n", cpm_obj, offset);
                   1150:                                printf("m 0x%x prev_address 0x%x\n", m,
                   1151:                                       prev_addr);
                   1152:                                panic("vm_allocate_cpm:  pages not contig!");
                   1153:                        }
                   1154:                }
                   1155:                prev_addr = m->phys_addr;
                   1156:        }
                   1157: #endif /* MACH_ASSERT */
                   1158: 
                   1159:        vm_object_deallocate(cpm_obj); /* kill extra ref */
                   1160: 
                   1161:        return kr;
                   1162: }
                   1163: 
                   1164: 
                   1165: #else  /* VM_CPM */
                   1166: 
                   1167: /*
                   1168:  *     Interface is defined in all cases, but unless the kernel
                   1169:  *     is built explicitly for this option, the interface does
                   1170:  *     nothing.
                   1171:  */
                   1172: 
                   1173: kern_return_t
                   1174: vm_allocate_cpm(
                   1175:        host_t                  host,
                   1176:        register vm_map_t       map,
                   1177:        register vm_offset_t    *addr,
                   1178:        register vm_size_t      size,
                   1179:        int                     flags)
                   1180: {
                   1181:        return KERN_FAILURE;
                   1182: }
                   1183: 
                   1184: /*
                   1185:  */
                   1186: kern_return_t
                   1187: mach_memory_object_memory_entry(
                   1188:        host_t          host,
                   1189:        boolean_t       internal,
                   1190:        vm_size_t       size,
                   1191:        vm_prot_t       permission,
                   1192:        ipc_port_t      pager,
                   1193:        ipc_port_t      *entry_handle)
                   1194: {
                   1195:        vm_named_entry_t        user_object;
                   1196:        ipc_port_t              user_handle;
                   1197:        ipc_port_t              previous;
                   1198:        kern_return_t           kr;
                   1199: 
                   1200:         if (host == HOST_NULL)
                   1201:                 return(KERN_INVALID_HOST);
                   1202: 
                   1203:        user_object = (vm_named_entry_t) 
                   1204:                        kalloc(sizeof (struct vm_named_entry));
                   1205:        if(user_object == NULL)
                   1206:                return KERN_FAILURE;
                   1207:        named_entry_lock_init(user_object);
                   1208:        user_handle = ipc_port_alloc_kernel();
                   1209:        ip_lock(user_handle);
                   1210: 
                   1211:        /* make a sonce right */
                   1212:        user_handle->ip_sorights++;
                   1213:        ip_reference(user_handle);
                   1214: 
                   1215:        user_handle->ip_destination = IP_NULL;
                   1216:        user_handle->ip_receiver_name = MACH_PORT_NULL;
                   1217:        user_handle->ip_receiver = ipc_space_kernel;
                   1218: 
                   1219:        /* make a send right */
                   1220:         user_handle->ip_mscount++;
                   1221:         user_handle->ip_srights++;
                   1222:         ip_reference(user_handle);
                   1223: 
                   1224:        ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
                   1225:        /* nsrequest unlocks user_handle */
                   1226: 
                   1227:        user_object->object = NULL;
                   1228:        user_object->size = size;
                   1229:        user_object->offset = 0;
                   1230:        user_object->backing.pager = pager;
                   1231:        user_object->protection = permission;
                   1232:        user_object->internal = internal;
                   1233:        user_object->is_sub_map = FALSE;
                   1234:        user_object->ref_count = 1;
                   1235: 
                   1236:        ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
                   1237:                                                        IKOT_NAMED_ENTRY);
                   1238:        *entry_handle = user_handle;
                   1239:        return KERN_SUCCESS;
                   1240: }      
                   1241: 
                   1242: 
                   1243: 
                   1244: /*
                   1245:  */
                   1246: 
                   1247: kern_return_t
                   1248: mach_make_memory_entry(
                   1249:        vm_map_t                target_map,
                   1250:        vm_size_t               *size,
                   1251:        vm_offset_t             offset,
                   1252:        vm_prot_t               permission,
                   1253:        ipc_port_t              *object_handle,
                   1254:        ipc_port_t              parent_entry)
                   1255: {
                   1256:        vm_map_version_t        version;
                   1257:        vm_named_entry_t        user_object;
                   1258:        ipc_port_t              user_handle;
                   1259:        ipc_port_t              previous;
                   1260:        kern_return_t           kr;
                   1261: 
                   1262:        /* needed for call to vm_map_lookup_locked */
                   1263:        boolean_t               wired;
                   1264:        vm_offset_t             obj_off;
                   1265:        vm_prot_t               prot;
                   1266:        vm_offset_t             lo_offset, hi_offset;
                   1267:        vm_behavior_t           behavior;
                   1268:        vm_object_t             object;
                   1269: 
                   1270:        /* needed for direct map entry manipulation */
                   1271:        vm_map_entry_t  map_entry;
                   1272:        vm_map_t        local_map;
                   1273:        vm_size_t       mappable_size;
                   1274: 
                   1275:        
                   1276:        user_object = (vm_named_entry_t) 
                   1277:                        kalloc(sizeof (struct vm_named_entry));
                   1278:        if(user_object == NULL)
                   1279:                return KERN_FAILURE;
                   1280:        named_entry_lock_init(user_object);
                   1281:        user_handle = ipc_port_alloc_kernel();
                   1282:        ip_lock(user_handle);
                   1283: 
                   1284:        /* make a sonce right */
                   1285:        user_handle->ip_sorights++;
                   1286:        ip_reference(user_handle);
                   1287: 
                   1288:        user_handle->ip_destination = IP_NULL;
                   1289:        user_handle->ip_receiver_name = MACH_PORT_NULL;
                   1290:        user_handle->ip_receiver = ipc_space_kernel;
                   1291: 
                   1292:        /* make a send right */
                   1293:         user_handle->ip_mscount++;
                   1294:         user_handle->ip_srights++;
                   1295:         ip_reference(user_handle);
                   1296: 
                   1297:        ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
                   1298:        /* nsrequest unlocks user_handle */
                   1299: 
                   1300:        user_object->backing.pager = NULL;
                   1301:        user_object->ref_count = 1;
                   1302: 
                   1303:        if(parent_entry == NULL) {
                   1304:        /* Create a named object based on address range within the task map */
                   1305:        /* Go find the object at given address */
                   1306: 
                   1307:                permission &= VM_PROT_ALL;
                   1308:                vm_map_lock_read(target_map);
                   1309: 
                   1310:                /* get the object associated with the target address */
                   1311:                /* note we check the permission of the range against */
                   1312:                /* that requested by the caller */
                   1313: 
                   1314:                kr = vm_map_lookup_locked(&target_map, offset, 
                   1315:                                permission, &version,
                   1316:                                &object, &obj_off, &prot, &wired, &behavior,
                   1317:                                &lo_offset, &hi_offset);
                   1318:                if (kr != KERN_SUCCESS) {
                   1319:                        vm_map_unlock_read(target_map);
                   1320:                        goto make_mem_done;
                   1321:                }
                   1322:                if ((prot & permission) != permission) {
                   1323:                        kr = KERN_INVALID_RIGHT;
                   1324:                        vm_object_unlock(object);
                   1325:                        vm_map_unlock_read(target_map);
                   1326:                        goto make_mem_done;
                   1327:                }
                   1328: 
                   1329:                /* We have an object, now check to see if this object */
                   1330:                /* is suitable.  If not, create a shadow and share that */
                   1331:                
                   1332:                local_map = target_map;
                   1333: redo_lookup:
                   1334:                while(TRUE) {
                   1335:                   if(!vm_map_lookup_entry(local_map, offset, &map_entry)) {
                   1336:                        kr = KERN_INVALID_ARGUMENT;
                   1337:                         vm_object_unlock(object);
                   1338:                         vm_map_unlock_read(target_map);
                   1339:                         goto make_mem_done;
                   1340:                   }
                   1341:                   if(!(map_entry->is_sub_map)) {
                   1342:                      if(map_entry->object.vm_object != object) {
                   1343:                         kr = KERN_INVALID_ARGUMENT;
                   1344:                          vm_object_unlock(object);
                   1345:                          vm_map_unlock_read(target_map);
                   1346:                          goto make_mem_done;
                   1347:                      }
                   1348:                      break;
                   1349:                   } else {
                   1350:                        local_map = map_entry->object.sub_map;
                   1351:                        vm_map_lock_read(local_map);
                   1352:                        vm_map_unlock_read(target_map);
                   1353:                        target_map = local_map;
                   1354:                   }
                   1355:                }
                   1356:                if(((map_entry->max_protection) & permission) != permission) {
                   1357:                         kr = KERN_INVALID_RIGHT;
                   1358:                          vm_object_unlock(object);
                   1359:                          vm_map_unlock_read(target_map);
                   1360:                          goto make_mem_done;
                   1361:                }
                   1362:                if(object->internal) {
                   1363:                        /* vm_map_lookup_locked will create a shadow if   */
                   1364:                        /* needs_copy is set but does not check for the   */
                   1365:                        /* other two conditions shown. It is important to */ 
                   1366:                        /* set up an object which will not be pulled from */
                   1367:                        /* under us.  */
                   1368: 
                   1369:                        if (map_entry->needs_copy  || object->shadowed ||
                   1370:                             (object->size > ((vm_size_t)map_entry->vme_end -
                   1371:                             map_entry->vme_start))) {
                   1372:                                if (vm_map_lock_read_to_write(target_map)) {
                   1373:                                        vm_map_lock_read(target_map);
                   1374:                                        goto redo_lookup;
                   1375:                                }
                   1376: 
                   1377: 
                   1378:                                /* create a shadow object */
                   1379: 
                   1380:                                vm_object_shadow(&map_entry->object.vm_object, 
                   1381:                                        &map_entry->offset, 
                   1382:                                        (map_entry->vme_end
                   1383:                                         - map_entry->vme_start));
                   1384:                                map_entry->needs_copy = FALSE;
                   1385:                                vm_object_unlock(object);
                   1386:                                object = map_entry->object.vm_object;
                   1387:                                vm_object_lock(object);
                   1388:                                object->size = map_entry->vme_end 
                   1389:                                                - map_entry->vme_start;
                   1390:                                obj_off = (offset - map_entry->vme_start) + 
                   1391:                                                        map_entry->offset;
                   1392:                                lo_offset = map_entry->offset;
                   1393:                                hi_offset = (map_entry->vme_end -
                   1394:                                        map_entry->vme_start) +
                   1395:                                        map_entry->offset;
                   1396: 
                   1397:                                vm_map_lock_write_to_read(target_map);
                   1398: 
                   1399:                        }
                   1400:                }
                   1401: 
                   1402:                /* note: in the future we can (if necessary) allow for  */
                   1403:                /* memory object lists, this will better support        */
                   1404:                /* fragmentation, but is it necessary?  The user should */
                   1405:                /* be encouraged to create address space oriented       */
                   1406:                /* shared objects from CLEAN memory regions which have  */
                   1407:                /* a known and defined history.  i.e. no inheritence    */
                   1408:                /* share, make this call before making the region the   */
                   1409:                /* target of ipc's, etc.  The code above, protecting    */
                   1410:                /* against delayed copy, etc. is mostly defensive.      */
                   1411: 
                   1412: 
                   1413: 
                   1414:                object->true_share = TRUE;
                   1415:                user_object->object = object;
                   1416:                user_object->internal = object->internal;
                   1417:                user_object->is_sub_map = FALSE;
                   1418:                user_object->offset = obj_off;
                   1419:                user_object->protection = permission;
                   1420: 
                   1421:                /* the size of mapped entry that overlaps with our region */
                   1422:                /* which is targeted for share.                           */
                   1423:                /* (entry_end - entry_start) -                            */
                   1424:                /*                   offset of our beg addr within entry  */
                   1425:                /* it corresponds to this:                                */
                   1426: 
                   1427:                mappable_size  =  hi_offset - obj_off;
                   1428:                if(*size > mappable_size)
                   1429:                        *size = mappable_size;
                   1430: 
                   1431:                user_object->size = *size;
                   1432: 
                   1433:                /* user_object pager and internal fields are not used */
                   1434:                /* when the object field is filled in.                */
                   1435: 
                   1436:                object->ref_count++; /* we now point to this object, hold on */
                   1437:                vm_object_res_reference(object);
                   1438:                vm_object_unlock(object);
                   1439:                ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
                   1440:                                                        IKOT_NAMED_ENTRY);
                   1441:                *size = user_object->size;
                   1442:                *object_handle = user_handle;
                   1443:                vm_map_unlock_read(target_map);
                   1444:                return KERN_SUCCESS;
                   1445:        } else {
                   1446: 
                   1447:                vm_named_entry_t        parent_object;
                   1448: 
                   1449:                /* The new object will be base on an existing named object */
                   1450:                if(ip_kotype(parent_entry) != IKOT_NAMED_ENTRY) {
                   1451:                        kr = KERN_INVALID_ARGUMENT;
                   1452:                        goto make_mem_done;
                   1453:                }
                   1454:                parent_object =  (vm_named_entry_t)parent_entry->ip_kobject;
                   1455:                if(permission & parent_object->protection != permission) {
                   1456:                        kr = KERN_INVALID_ARGUMENT;
                   1457:                        goto make_mem_done;
                   1458:                }
                   1459:                if((offset + *size) > parent_object->size) {
                   1460:                        kr = KERN_INVALID_ARGUMENT;
                   1461:                        goto make_mem_done;
                   1462:                }
                   1463: 
                   1464:                user_object->object = parent_object->object;
                   1465:                user_object->size = *size;
                   1466:                user_object->offset = parent_object->offset + offset;
                   1467:                user_object->protection = permission;
                   1468:                if(parent_object->is_sub_map) {
                   1469:                   user_object->backing.map = parent_object->backing.map;
                   1470:                   vm_map_lock(user_object->backing.map);
                   1471:                   user_object->backing.map->ref_count++;
                   1472:                   vm_map_unlock(user_object->backing.map);
                   1473:                }
                   1474:                else {
                   1475:                   user_object->backing.pager = parent_object->backing.pager;
                   1476:                }
                   1477:                user_object->internal = parent_object->internal;
                   1478:                user_object->is_sub_map = parent_object->is_sub_map;
                   1479: 
                   1480:                if(parent_object->object != NULL) {
                   1481:                        /* we now point to this object, hold on */
                   1482:                        vm_object_reference(parent_object->object); 
                   1483:                        vm_object_lock(parent_object->object);
                   1484:                        parent_object->object->true_share = TRUE;
                   1485:                        vm_object_unlock(parent_object->object);
                   1486:                }
                   1487:                ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
                   1488:                                                        IKOT_NAMED_ENTRY);
                   1489:                *object_handle = user_handle;
                   1490:                return KERN_SUCCESS;
                   1491:        }
                   1492: 
                   1493: 
                   1494: 
                   1495: make_mem_done:
                   1496:        ipc_port_dealloc_kernel(user_handle);
                   1497:        kfree((vm_offset_t)user_object, sizeof (struct vm_named_entry));
                   1498:        return kr;
                   1499: }
                   1500: 
                   1501: /*
                   1502:  */
                   1503: 
                   1504: kern_return_t
                   1505: vm_region_object_create(
                   1506:        vm_map_t                target_map,
                   1507:        vm_size_t               size,
                   1508:        ipc_port_t              *object_handle)
                   1509: {
                   1510:        vm_named_entry_t        user_object;
                   1511:        ipc_port_t              user_handle;
                   1512:        kern_return_t           kr;
                   1513: 
                   1514:        pmap_t          new_pmap = pmap_create((vm_size_t) 0);
                   1515:        ipc_port_t      previous;
                   1516:        vm_map_t        new_map;
                   1517:        
                   1518:        if(new_pmap == PMAP_NULL)
                   1519:                return KERN_FAILURE;
                   1520:        user_object = (vm_named_entry_t) 
                   1521:                        kalloc(sizeof (struct vm_named_entry));
                   1522:        if(user_object == NULL) {
                   1523:                pmap_destroy(new_pmap);
                   1524:                return KERN_FAILURE;
                   1525:        }
                   1526:        named_entry_lock_init(user_object);
                   1527:        user_handle = ipc_port_alloc_kernel();
                   1528: 
                   1529: 
                   1530:        ip_lock(user_handle);
                   1531: 
                   1532:        /* make a sonce right */
                   1533:        user_handle->ip_sorights++;
                   1534:        ip_reference(user_handle);
                   1535: 
                   1536:        user_handle->ip_destination = IP_NULL;
                   1537:        user_handle->ip_receiver_name = MACH_PORT_NULL;
                   1538:        user_handle->ip_receiver = ipc_space_kernel;
                   1539: 
                   1540:        /* make a send right */
                   1541:         user_handle->ip_mscount++;
                   1542:         user_handle->ip_srights++;
                   1543:         ip_reference(user_handle);
                   1544: 
                   1545:        ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
                   1546:        /* nsrequest unlocks user_handle */
                   1547: 
                   1548:        /* Create a named object based on a submap of specified size */
                   1549: 
                   1550:        new_map = vm_map_create(new_pmap, 0, size, TRUE);
                   1551:        user_object->backing.map = new_map;
                   1552: 
                   1553: 
                   1554:        user_object->object = VM_OBJECT_NULL;
                   1555:        user_object->internal = TRUE;
                   1556:        user_object->is_sub_map = TRUE;
                   1557:        user_object->offset = 0;
                   1558:        user_object->protection = VM_PROT_ALL;
                   1559:        user_object->size = size;
                   1560:        user_object->ref_count = 1;
                   1561: 
                   1562:        ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
                   1563:                                                        IKOT_NAMED_ENTRY);
                   1564:        *object_handle = user_handle;
                   1565:        return KERN_SUCCESS;
                   1566: 
                   1567: }
                   1568: 
                   1569: void
                   1570: mach_destroy_memory_entry(
                   1571:        ipc_port_t      port)
                   1572: {
                   1573:        vm_named_entry_t        named_entry;
                   1574: #if MACH_ASSERT
                   1575:        assert(ip_kotype(port) == IKOT_NAMED_ENTRY);
                   1576: #endif /* MACH_ASSERT */
                   1577:        named_entry = (vm_named_entry_t)port->ip_kobject;
                   1578:        mutex_lock(&(named_entry)->Lock);
                   1579:        named_entry->ref_count-=1;
                   1580:        if(named_entry->ref_count == 0) {
                   1581:                if(named_entry->object) {
                   1582:                        /* release the memory object we've been pointing to */
                   1583:                        vm_object_deallocate(named_entry->object);
                   1584:                }
                   1585:                if(named_entry->is_sub_map) {
                   1586:                        vm_map_deallocate(named_entry->backing.map);
                   1587:                }
                   1588:                kfree((vm_offset_t)port->ip_kobject, 
                   1589:                                sizeof (struct vm_named_entry));
                   1590:        } else
                   1591:                mutex_unlock(&(named_entry)->Lock);
                   1592: }
                   1593: 
                   1594: 
                   1595: kern_return_t
                   1596: vm_map_page_query(
                   1597:        vm_map_t                target_map,
                   1598:        vm_offset_t             offset,
                   1599:        int                     *disposition,
                   1600:        int                     *ref_count)
                   1601: {
                   1602:        vm_map_entry_t  map_entry;
                   1603:        vm_object_t     object;
                   1604:        vm_page_t       m;
                   1605: 
                   1606: restart_page_query:
                   1607:        *disposition = 0;
                   1608:        *ref_count = 0;
                   1609:        vm_map_lock(target_map);
                   1610:        if(!vm_map_lookup_entry(target_map, offset, &map_entry)) {
                   1611:                vm_map_unlock(target_map);
                   1612:                return KERN_FAILURE;
                   1613:        }
                   1614:        offset -= map_entry->vme_start;  /* adjust to offset within entry */
                   1615:        offset += map_entry->offset;     /* adjust to target object offset */
                   1616:        if(map_entry->object.vm_object != VM_OBJECT_NULL) {
                   1617:                if(!map_entry->is_sub_map) {
                   1618:                        object = map_entry->object.vm_object;
                   1619:                } else {
                   1620:                        vm_map_unlock(target_map);
                   1621:                        target_map = map_entry->object.sub_map;
                   1622:                        goto restart_page_query;
                   1623:                }
                   1624:        } else {
                   1625:                vm_map_unlock(target_map);
                   1626:                return KERN_FAILURE;
                   1627:        }
                   1628:        vm_object_lock(object);
                   1629:        vm_map_unlock(target_map);
                   1630:        while(TRUE) {
                   1631:                m = vm_page_lookup(object, offset);
                   1632:                if (m != VM_PAGE_NULL) {
                   1633:                        *disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
                   1634:                        break;
                   1635:                } else {
                   1636:                        if(object->shadow) {
                   1637:                                offset += object->shadow_offset;
                   1638:                                vm_object_unlock(object);
                   1639:                                object = object->shadow;
                   1640:                                vm_object_lock(object);
                   1641:                                continue;
                   1642:                        }
                   1643:                        vm_object_unlock(object);
                   1644:                        return KERN_FAILURE;
                   1645:                }
                   1646:        }
                   1647: 
                   1648:        /* The ref_count is not strictly accurate, it measures the number   */
                   1649:        /* of entities holding a ref on the object, they may not be mapping */
                   1650:        /* the object or may not be mapping the section holding the         */
                   1651:        /* target page but its still a ball park number and though an over- */
                   1652:        /* count, it picks up the copy-on-write cases                       */
                   1653: 
                   1654:        /* We could also get a picture of page sharing from pmap_attributes */
                   1655:        /* but this would under count as only faulted-in mappings would     */
                   1656:        /* show up.                                                         */
                   1657: 
                   1658:        *ref_count = object->ref_count;
                   1659: 
                   1660:        if (m->fictitious) {
                   1661:                *disposition |= VM_PAGE_QUERY_PAGE_FICTITIOUS;
                   1662:                vm_object_unlock(object);
                   1663:                return KERN_SUCCESS;
                   1664:        }
                   1665: 
                   1666:        if (m->dirty)
                   1667:                *disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
                   1668:        else if(pmap_is_modified(m->phys_addr))
                   1669:                *disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
                   1670: 
                   1671:        if (m->reference)
                   1672:                *disposition |= VM_PAGE_QUERY_PAGE_REF;
                   1673:        else if(pmap_is_referenced(m->phys_addr))
                   1674:                *disposition |= VM_PAGE_QUERY_PAGE_REF;
                   1675: 
                   1676:        vm_object_unlock(object);
                   1677:        return KERN_SUCCESS;
                   1678:        
                   1679: }
                   1680: 
                   1681: kern_return_t
                   1682: set_dp_control_port(
                   1683:        host_t          host,
                   1684:        ipc_port_t      control_port)   
                   1685: {
                   1686:         if (host == HOST_NULL)
                   1687:                 return (KERN_INVALID_HOST);
                   1688:        dynamic_pager_control_port = control_port;
                   1689:        return KERN_SUCCESS;
                   1690: }
                   1691: 
                   1692: kern_return_t
                   1693: get_dp_control_port(
                   1694:        host_t          host,
                   1695:        ipc_port_t      *control_port)  
                   1696: {
                   1697:         if (host == HOST_NULL)
                   1698:                 return (KERN_INVALID_HOST);
                   1699:        *control_port = dynamic_pager_control_port;
                   1700:        return KERN_SUCCESS;
                   1701:        
                   1702: }
                   1703: 
                   1704: void
                   1705: mach_destroy_upl(
                   1706:        ipc_port_t      port)
                   1707: {
                   1708:        upl_t   upl;
                   1709: #if MACH_ASSERT
                   1710:        assert(ip_kotype(port) == IKOT_NAMED_ENTRY);
                   1711: #endif /* MACH_ASSERT */
                   1712:        upl = (upl_t)port->ip_kobject;
                   1713:        mutex_lock(&(upl)->Lock);
                   1714:        upl->ref_count-=1;
                   1715:        if(upl->ref_count == 0) {
                   1716:                mutex_unlock(&(upl)->Lock);
                   1717:                upl_abort(upl, UPL_ABORT_ERROR);
                   1718:        } else
                   1719:                mutex_unlock(&(upl)->Lock);
                   1720: }
                   1721: 
                   1722: kern_return_t
                   1723: vm_object_upl_request(
                   1724:        vm_object_t             object,
                   1725:        vm_object_offset_t      offset,
                   1726:        vm_size_t               size,
                   1727:        ipc_port_t              *upl,
                   1728:        upl_page_info_t         *page_list,
                   1729:        mach_msg_type_number_t  *count,
                   1730:        int                     cntrl_flags)
                   1731: {
                   1732:        upl_t   upl_object;
                   1733:        ipc_port_t      upl_port;
                   1734:        ipc_port_t      previous;
                   1735:        upl_page_info_t *pl;
                   1736:        kern_return_t   kr;
                   1737: 
                   1738:        pl = page_list;
                   1739:        kr = vm_fault_list_request(object, offset, size, &upl_object,
                   1740:                                                &pl, *count, cntrl_flags);
                   1741: 
                   1742:        
                   1743:        if(kr != KERN_SUCCESS) {
                   1744:                *upl = MACH_PORT_NULL;
                   1745:                return KERN_FAILURE;
                   1746:        }
                   1747: 
                   1748:        upl_port = ipc_port_alloc_kernel();
                   1749: 
                   1750: 
                   1751:        ip_lock(upl_port);
                   1752: 
                   1753:        /* make a sonce right */
                   1754:        upl_port->ip_sorights++;
                   1755:        ip_reference(upl_port);
                   1756: 
                   1757:        upl_port->ip_destination = IP_NULL;
                   1758:        upl_port->ip_receiver_name = MACH_PORT_NULL;
                   1759:        upl_port->ip_receiver = ipc_space_kernel;
                   1760: 
                   1761:        /* make a send right */
                   1762:         upl_port->ip_mscount++;
                   1763:         upl_port->ip_srights++;
                   1764:         ip_reference(upl_port);
                   1765: 
                   1766:        ipc_port_nsrequest(upl_port, 1, upl_port, &previous);
                   1767:        /* nsrequest unlocks user_handle */
                   1768: 
                   1769:        /* Create a named object based on a submap of specified size */
                   1770: 
                   1771: 
                   1772:        ipc_kobject_set(upl_port, (ipc_kobject_t) upl_object, IKOT_UPL);
                   1773:        *upl = upl_port;
                   1774:        return KERN_SUCCESS;
                   1775: }
                   1776: 
                   1777: kern_return_t
                   1778: vm_pager_upl_request(
                   1779:        vm_object_t             object,
                   1780:        vm_object_offset_t      offset,
                   1781:        vm_size_t               size,
                   1782:        vm_size_t               super_size,
                   1783:        ipc_port_t              *upl,
                   1784:        upl_page_info_t         *page_list,
                   1785:        mach_msg_type_number_t  *count,
                   1786:        int                     cntrl_flags)
                   1787: {
                   1788:        upl_t   upl_object;
                   1789:        ipc_port_t      upl_port;
                   1790:        ipc_port_t      previous;
                   1791:        upl_page_info_t *pl;
                   1792:        kern_return_t   kr;
                   1793: 
                   1794:        pl = page_list;
                   1795:        kr = upl_system_list_request(object, offset, size, super_size, 
                   1796:                                        &upl_object, &pl, *count, cntrl_flags);
                   1797: 
                   1798:        if(kr != KERN_SUCCESS) {
                   1799:                *upl = MACH_PORT_NULL;
                   1800:                return KERN_FAILURE;
                   1801:        }
                   1802: 
                   1803:        
                   1804:        upl_port = ipc_port_alloc_kernel();
                   1805: 
                   1806: 
                   1807:        ip_lock(upl_port);
                   1808: 
                   1809:        /* make a sonce right */
                   1810:        upl_port->ip_sorights++;
                   1811:        ip_reference(upl_port);
                   1812: 
                   1813:        upl_port->ip_destination = IP_NULL;
                   1814:        upl_port->ip_receiver_name = MACH_PORT_NULL;
                   1815:        upl_port->ip_receiver = ipc_space_kernel;
                   1816: 
                   1817:        /* make a send right */
                   1818:         upl_port->ip_mscount++;
                   1819:         upl_port->ip_srights++;
                   1820:         ip_reference(upl_port);
                   1821: 
                   1822:        ipc_port_nsrequest(upl_port, 1, upl_port, &previous);
                   1823:        /* nsrequest unlocks user_handle */
                   1824: 
                   1825:        /* Create a named object based on a submap of specified size */
                   1826: 
                   1827: 
                   1828:        ipc_kobject_set(upl_port, (ipc_kobject_t) upl_object, IKOT_UPL);
                   1829:        *upl = upl_port;
                   1830:        return KERN_SUCCESS;
                   1831: }
                   1832: 
                   1833: kern_return_t
                   1834: vm_upl_map(
                   1835:        vm_map_t        map,
                   1836:        ipc_port_t      upl_port,
                   1837:        vm_offset_t     *dst_addr)
                   1838: {
                   1839:        upl_t           upl;
                   1840:        kern_return_t   kr;
                   1841: 
                   1842:        if (!IP_VALID(upl_port)) {
                   1843:                return KERN_INVALID_ARGUMENT;
                   1844:        } else if (ip_kotype(upl_port) == IKOT_UPL) {
                   1845:                upl_lock(upl);
                   1846:                upl = (upl_t)upl_port->ip_kobject;
                   1847:                kr = upl_map(map, upl, dst_addr);
                   1848:                upl_unlock(upl);
                   1849:                return kr;
                   1850:        } else {
                   1851:                return KERN_FAILURE;
                   1852:        }
                   1853: }
                   1854: 
                   1855: 
                   1856: kern_return_t
                   1857: vm_upl_unmap(
                   1858:        vm_map_t        map,
                   1859:        ipc_port_t      upl_port)
                   1860: {
                   1861:        upl_t           upl;
                   1862:        kern_return_t   kr;
                   1863: 
                   1864:        if (!IP_VALID(upl_port)) {
                   1865:                return KERN_INVALID_ARGUMENT;
                   1866:        } else if (ip_kotype(upl_port) == IKOT_UPL) {
                   1867:                upl_lock(upl);
                   1868:                upl = (upl_t)upl_port->ip_kobject;
                   1869:                kr = upl_un_map(map, upl);
                   1870:                upl_unlock(upl);
                   1871:                return kr;
                   1872:        } else {
                   1873:                return KERN_FAILURE;
                   1874:        }
                   1875: }
                   1876: 
                   1877: kern_return_t
                   1878: vm_upl_commit(
                   1879:        upl_t                   upl,
                   1880:        upl_page_list_ptr_t     page_list,
                   1881:        mach_msg_type_number_t  count)
                   1882: {
                   1883:        kern_return_t kr;
                   1884:        upl_lock(upl);
                   1885:        if(count) {
                   1886:                kr = upl_commit(upl, (upl_page_info_t *)page_list);
                   1887:        } else {
                   1888:                kr = upl_commit(upl, (upl_page_info_t *) NULL);
                   1889:        }
                   1890:        upl_unlock(upl);
                   1891:        return kr;
                   1892: }
                   1893: 
                   1894: kern_return_t
                   1895: vm_upl_commit_range(
                   1896:        upl_t                   upl,
                   1897:        vm_offset_t             offset,
                   1898:        vm_size_t               size,
                   1899:        upl_page_list_ptr_t     page_list,
                   1900:        boolean_t               free_on_empty,
                   1901:        mach_msg_type_number_t  count)
                   1902: {
                   1903:        kern_return_t kr;
                   1904:        upl_lock(upl);
                   1905:        if(count) {
                   1906:                kr = upl_commit_range(upl, offset, size, free_on_empty, 
                   1907:                                        (upl_page_info_t *)page_list);
                   1908:        } else {
                   1909:                kr = upl_commit_range(upl, offset, size, free_on_empty,
                   1910:                                        (upl_page_info_t *) NULL);
                   1911:        }
                   1912:        upl_unlock(upl);
                   1913:        return kr;
                   1914: }
                   1915:        
                   1916: kern_return_t
                   1917: vm_upl_abort_range(
                   1918:        upl_t           upl,
                   1919:        vm_offset_t     offset,
                   1920:        vm_size_t       size,
                   1921:        int             abort_flags)
                   1922: {
                   1923:        kern_return_t kr;
                   1924:        upl_lock(upl);
                   1925:        kr = upl_abort_range(upl, offset, size, abort_flags);
                   1926:        upl_unlock(upl);
                   1927:        return kr;
                   1928: }
                   1929: 
                   1930: kern_return_t
                   1931: vm_upl_abort(
                   1932:        upl_t           upl,
                   1933:        int             abort_type)
                   1934: {
                   1935:        kern_return_t kr;
                   1936:        upl_lock(upl);
                   1937:        kr = upl_abort(upl, abort_type);
                   1938:        upl_unlock(upl);
                   1939:        return kr;
                   1940: }
                   1941: 
                   1942: #endif /* VM_CPM */

unix.superglobalmegacorp.com

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