Annotation of XNU/osfmk/vm/vm_user.c, revision 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.