Annotation of Gnu-Mach/vm/vm_user.c, revision 1.1.1.4

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File:   vm/vm_user.c
                     28:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     29:  * 
                     30:  *     User-exported virtual memory functions.
                     31:  */
                     32: 
                     33: #include <mach/boolean.h>
                     34: #include <mach/kern_return.h>
                     35: #include <mach/mach_types.h>   /* to get vm_address_t */
                     36: #include <mach/memory_object.h>
                     37: #include <mach/std_types.h>    /* to get pointer_t */
                     38: #include <mach/vm_attributes.h>
                     39: #include <mach/vm_param.h>
                     40: #include <mach/vm_statistics.h>
1.1.1.2   root       41: #include <mach/vm_cache_statistics.h>
1.1       root       42: #include <kern/host.h>
                     43: #include <kern/task.h>
                     44: #include <vm/vm_fault.h>
1.1.1.2   root       45: #include <vm/vm_kern.h>
1.1       root       46: #include <vm/vm_map.h>
                     47: #include <vm/vm_object.h>
1.1.1.2   root       48: #include <vm/memory_object_proxy.h>
1.1       root       49: #include <vm/vm_page.h>
                     50: 
                     51: 
                     52: 
                     53: vm_statistics_data_t   vm_stat;
                     54: 
                     55: /*
                     56:  *     vm_allocate allocates "zero fill" memory in the specfied
                     57:  *     map.
                     58:  */
1.1.1.3   root       59: kern_return_t vm_allocate(
                     60:        vm_map_t        map,
                     61:        vm_offset_t     *addr,
                     62:        vm_size_t       size,
                     63:        boolean_t       anywhere)
1.1       root       64: {
                     65:        kern_return_t   result;
                     66: 
                     67:        if (map == VM_MAP_NULL)
                     68:                return(KERN_INVALID_ARGUMENT);
                     69:        if (size == 0) {
                     70:                *addr = 0;
                     71:                return(KERN_SUCCESS);
                     72:        }
                     73: 
                     74:        if (anywhere)
                     75:                *addr = vm_map_min(map);
                     76:        else
                     77:                *addr = trunc_page(*addr);
                     78:        size = round_page(size);
                     79: 
                     80:        result = vm_map_enter(
                     81:                        map,
                     82:                        addr,
                     83:                        size,
                     84:                        (vm_offset_t)0,
                     85:                        anywhere,
                     86:                        VM_OBJECT_NULL,
                     87:                        (vm_offset_t)0,
                     88:                        FALSE,
                     89:                        VM_PROT_DEFAULT,
                     90:                        VM_PROT_ALL,
                     91:                        VM_INHERIT_DEFAULT);
                     92: 
                     93:        return(result);
                     94: }
                     95: 
                     96: /*
                     97:  *     vm_deallocate deallocates the specified range of addresses in the
                     98:  *     specified address map.
                     99:  */
1.1.1.3   root      100: kern_return_t vm_deallocate(
                    101:        vm_map_t                map,
                    102:        vm_offset_t             start,
                    103:        vm_size_t               size)
1.1       root      104: {
                    105:        if (map == VM_MAP_NULL)
                    106:                return(KERN_INVALID_ARGUMENT);
                    107: 
                    108:        if (size == (vm_offset_t) 0)
                    109:                return(KERN_SUCCESS);
                    110: 
                    111:        return(vm_map_remove(map, trunc_page(start), round_page(start+size)));
                    112: }
                    113: 
                    114: /*
                    115:  *     vm_inherit sets the inheritance of the specified range in the
                    116:  *     specified map.
                    117:  */
1.1.1.3   root      118: kern_return_t vm_inherit(
                    119:        vm_map_t                map,
                    120:        vm_offset_t             start,
                    121:        vm_size_t               size,
                    122:        vm_inherit_t            new_inheritance)
1.1       root      123: {
                    124:        if (map == VM_MAP_NULL)
                    125:                return(KERN_INVALID_ARGUMENT);
                    126: 
                    127:         switch (new_inheritance) {
                    128:         case VM_INHERIT_NONE:
                    129:         case VM_INHERIT_COPY:
                    130:         case VM_INHERIT_SHARE:
                    131:                 break;
                    132:         default:
                    133:                 return(KERN_INVALID_ARGUMENT);
                    134:         }
                    135: 
                    136:        /*Check if range includes projected buffer;
                    137:          user is not allowed direct manipulation in that case*/
                    138:        if (projected_buffer_in_range(map, start, start+size))
                    139:                return(KERN_INVALID_ARGUMENT);
                    140: 
                    141:        return(vm_map_inherit(map,
                    142:                              trunc_page(start),
                    143:                              round_page(start+size),
                    144:                              new_inheritance));
                    145: }
                    146: 
                    147: /*
                    148:  *     vm_protect sets the protection of the specified range in the
                    149:  *     specified map.
                    150:  */
                    151: 
1.1.1.3   root      152: kern_return_t vm_protect(
                    153:        vm_map_t                map,
                    154:        vm_offset_t             start,
                    155:        vm_size_t               size,
                    156:        boolean_t               set_maximum,
                    157:        vm_prot_t               new_protection)
1.1       root      158: {
                    159:        if ((map == VM_MAP_NULL) || 
                    160:                (new_protection & ~(VM_PROT_ALL|VM_PROT_NOTIFY)))
                    161:                return(KERN_INVALID_ARGUMENT);
                    162: 
                    163:        /*Check if range includes projected buffer;
                    164:          user is not allowed direct manipulation in that case*/
                    165:        if (projected_buffer_in_range(map, start, start+size))
                    166:                return(KERN_INVALID_ARGUMENT);
                    167: 
                    168:        return(vm_map_protect(map,
                    169:                              trunc_page(start),
                    170:                              round_page(start+size),
                    171:                              new_protection,
                    172:                              set_maximum));
                    173: }
                    174: 
1.1.1.3   root      175: kern_return_t vm_statistics(
                    176:        vm_map_t                map,
                    177:        vm_statistics_data_t    *stat)
1.1       root      178: {
                    179:        if (map == VM_MAP_NULL)
                    180:                return(KERN_INVALID_ARGUMENT);
                    181: 
                    182:        *stat = vm_stat;
                    183: 
                    184:        stat->pagesize = PAGE_SIZE;
                    185:        stat->free_count = vm_page_free_count;
                    186:        stat->active_count = vm_page_active_count;
                    187:        stat->inactive_count = vm_page_inactive_count;
                    188:        stat->wire_count = vm_page_wire_count;
                    189: 
                    190:        return(KERN_SUCCESS);
                    191: }
                    192: 
1.1.1.2   root      193: kern_return_t vm_cache_statistics(
                    194:        vm_map_t                        map,
                    195:        vm_cache_statistics_data_t      *stats)
                    196: {
                    197:        if (map == VM_MAP_NULL)
                    198:                return KERN_INVALID_ARGUMENT;
                    199: 
                    200:        stats->cache_object_count = vm_object_cached_count;
                    201:        stats->cache_count = vm_object_cached_pages;
                    202: 
                    203:        /* XXX Not implemented yet */
                    204:        stats->active_tmp_count = 0;
                    205:        stats->inactive_tmp_count = 0;
                    206:        stats->active_perm_count = 0;
                    207:        stats->inactive_perm_count = 0;
                    208:        stats->dirty_count = 0;
                    209:        stats->laundry_count = 0;
                    210:        stats->writeback_count = 0;
                    211:        stats->slab_count = 0;
                    212:        stats->slab_reclaim_count = 0;
                    213:        return KERN_SUCCESS;
                    214: }
                    215: 
1.1       root      216: /*
                    217:  * Handle machine-specific attributes for a mapping, such
                    218:  * as cachability, migrability, etc.
                    219:  */
1.1.1.3   root      220: kern_return_t vm_machine_attribute(
                    221:        vm_map_t        map,
                    222:        vm_address_t    address,
                    223:        vm_size_t       size,
                    224:        vm_machine_attribute_t  attribute,
                    225:        vm_machine_attribute_val_t* value)              /* IN/OUT */
1.1       root      226: {
                    227:        if (map == VM_MAP_NULL)
                    228:                return(KERN_INVALID_ARGUMENT);
                    229: 
                    230:        /*Check if range includes projected buffer;
                    231:          user is not allowed direct manipulation in that case*/
                    232:        if (projected_buffer_in_range(map, address, address+size))
                    233:                return(KERN_INVALID_ARGUMENT);
                    234: 
                    235:        return vm_map_machine_attribute(map, address, size, attribute, value);
                    236: }
                    237: 
1.1.1.3   root      238: kern_return_t vm_read(
                    239:        vm_map_t        map,
                    240:        vm_address_t    address,
                    241:        vm_size_t       size,
                    242:        pointer_t       *data,
                    243:        vm_size_t       *data_size)
1.1       root      244: {
                    245:        kern_return_t   error;
                    246:        vm_map_copy_t   ipc_address;
                    247: 
                    248:        if (map == VM_MAP_NULL)
                    249:                return(KERN_INVALID_ARGUMENT);
                    250: 
                    251:        if ((error = vm_map_copyin(map,
                    252:                                address,
                    253:                                size,
                    254:                                FALSE,  /* src_destroy */
                    255:                                &ipc_address)) == KERN_SUCCESS) {
                    256:                *data = (pointer_t) ipc_address;
                    257:                *data_size = size;
                    258:        }
                    259:        return(error);
                    260: }
                    261: 
1.1.1.3   root      262: kern_return_t vm_write(
                    263:        vm_map_t        map,
                    264:        vm_address_t    address,
                    265:        pointer_t       data,
                    266:        vm_size_t       size)
1.1       root      267: {
                    268:        if (map == VM_MAP_NULL)
                    269:                return KERN_INVALID_ARGUMENT;
                    270: 
                    271:        return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data,
                    272:                                     FALSE /* interruptible XXX */);
                    273: }
                    274: 
1.1.1.3   root      275: kern_return_t vm_copy(
                    276:        vm_map_t        map,
                    277:        vm_address_t    source_address,
                    278:        vm_size_t       size,
                    279:        vm_address_t    dest_address)
1.1       root      280: {
                    281:        vm_map_copy_t copy;
                    282:        kern_return_t kr;
                    283: 
                    284:        if (map == VM_MAP_NULL)
                    285:                return KERN_INVALID_ARGUMENT;
                    286: 
                    287:        kr = vm_map_copyin(map, source_address, size,
                    288:                           FALSE, &copy);
                    289:        if (kr != KERN_SUCCESS)
                    290:                return kr;
                    291: 
                    292:        kr = vm_map_copy_overwrite(map, dest_address, copy,
                    293:                                   FALSE /* interruptible XXX */);
                    294:        if (kr != KERN_SUCCESS) {
                    295:                vm_map_copy_discard(copy);
                    296:                return kr;
                    297:        }
                    298: 
                    299:        return KERN_SUCCESS;
                    300: }
                    301: 
1.1.1.2   root      302: 
1.1       root      303: /*
                    304:  *     Routine:        vm_map
                    305:  */
                    306: kern_return_t vm_map(
1.1.1.3   root      307:        vm_map_t        target_map,
                    308:        vm_offset_t     *address,
                    309:        vm_size_t       size,
                    310:        vm_offset_t     mask,
                    311:        boolean_t       anywhere,
                    312:        ipc_port_t      memory_object,
                    313:        vm_offset_t     offset,
                    314:        boolean_t       copy,
                    315:        vm_prot_t       cur_protection,
                    316:        vm_prot_t       max_protection,
                    317:        vm_inherit_t    inheritance)
1.1       root      318: {
                    319:        vm_object_t     object;
                    320:        kern_return_t   result;
                    321: 
                    322:        if ((target_map == VM_MAP_NULL) ||
                    323:            (cur_protection & ~VM_PROT_ALL) ||
                    324:            (max_protection & ~VM_PROT_ALL))
                    325:                return(KERN_INVALID_ARGUMENT);
                    326: 
                    327:         switch (inheritance) {
                    328:         case VM_INHERIT_NONE:
                    329:         case VM_INHERIT_COPY:
                    330:         case VM_INHERIT_SHARE:
                    331:                 break;
                    332:         default:
                    333:                 return(KERN_INVALID_ARGUMENT);
                    334:         }
                    335: 
1.1.1.2   root      336:        if (size == 0)
                    337:                return KERN_INVALID_ARGUMENT;
                    338: 
1.1       root      339:        *address = trunc_page(*address);
                    340:        size = round_page(size);
                    341: 
                    342:        if (!IP_VALID(memory_object)) {
                    343:                object = VM_OBJECT_NULL;
                    344:                offset = 0;
                    345:                copy = FALSE;
                    346:        } else if ((object = vm_object_enter(memory_object, size, FALSE))
                    347:                        == VM_OBJECT_NULL)
1.1.1.2   root      348:          {
                    349:            ipc_port_t real_memobj;
                    350:            vm_prot_t prot;
                    351:            result = memory_object_proxy_lookup (memory_object, &real_memobj,
                    352:                                                 &prot);
                    353:            if (result != KERN_SUCCESS)
                    354:              return result;
                    355: 
                    356:            /* Reduce the allowed access to the memory object.  */
                    357:            max_protection &= prot;
                    358:            cur_protection &= prot;
                    359: 
                    360:            if ((object = vm_object_enter(real_memobj, size, FALSE))
                    361:                == VM_OBJECT_NULL)
                    362:              return KERN_INVALID_ARGUMENT;
                    363:          }
1.1       root      364: 
                    365:        /*
                    366:         *      Perform the copy if requested
                    367:         */
                    368: 
                    369:        if (copy) {
                    370:                vm_object_t     new_object;
                    371:                vm_offset_t     new_offset;
                    372: 
                    373:                result = vm_object_copy_strategically(object, offset, size,
                    374:                                &new_object, &new_offset,
                    375:                                &copy);
                    376: 
                    377:                /*
                    378:                 *      Throw away the reference to the
                    379:                 *      original object, as it won't be mapped.
                    380:                 */
                    381: 
                    382:                vm_object_deallocate(object);
                    383: 
                    384:                if (result != KERN_SUCCESS)
                    385:                        return (result);
                    386: 
                    387:                object = new_object;
                    388:                offset = new_offset;
                    389:        }
                    390: 
                    391:        if ((result = vm_map_enter(target_map,
                    392:                                address, size, mask, anywhere,
                    393:                                object, offset,
                    394:                                copy,
                    395:                                cur_protection, max_protection, inheritance
                    396:                                )) != KERN_SUCCESS)
                    397:                vm_object_deallocate(object);
                    398:        return(result);
                    399: }
                    400: 
                    401: /*
                    402:  *     Specify that the range of the virtual address space
                    403:  *     of the target task must not cause page faults for
                    404:  *     the indicated accesses.
                    405:  *
                    406:  *     [ To unwire the pages, specify VM_PROT_NONE. ]
                    407:  */
1.1.1.4 ! root      408: kern_return_t vm_wire(port, map, start, size, access)
        !           409:        const ipc_port_t        port;
1.1.1.3   root      410:        vm_map_t                map;
1.1       root      411:        vm_offset_t             start;
                    412:        vm_size_t               size;
                    413:        vm_prot_t               access;
                    414: {
1.1.1.4 ! root      415:        boolean_t priv;
        !           416: 
        !           417:        if (!IP_VALID(port))
        !           418:                return KERN_INVALID_HOST;
        !           419: 
        !           420:        ip_lock(port);
        !           421:        if (!ip_active(port) ||
        !           422:                  (ip_kotype(port) != IKOT_HOST_PRIV
        !           423:                && ip_kotype(port) != IKOT_HOST))
        !           424:        {
        !           425:                ip_unlock(port);
1.1       root      426:                return KERN_INVALID_HOST;
1.1.1.4 ! root      427:        }
        !           428: 
        !           429:        priv = ip_kotype(port) == IKOT_HOST_PRIV;
        !           430:        ip_unlock(port);
1.1       root      431: 
                    432:        if (map == VM_MAP_NULL)
                    433:                return KERN_INVALID_TASK;
                    434: 
                    435:        if (access & ~VM_PROT_ALL)
                    436:                return KERN_INVALID_ARGUMENT;
                    437: 
                    438:        /*Check if range includes projected buffer;
                    439:          user is not allowed direct manipulation in that case*/
                    440:        if (projected_buffer_in_range(map, start, start+size))
                    441:                return(KERN_INVALID_ARGUMENT);
                    442: 
1.1.1.4 ! root      443:        /* TODO: make it tunable */
        !           444:        if (!priv && access != VM_PROT_NONE && map->user_wired + size > 65536)
        !           445:                return KERN_NO_ACCESS;
        !           446: 
1.1       root      447:        return vm_map_pageable_user(map,
                    448:                                    trunc_page(start),
                    449:                                    round_page(start+size),
                    450:                                    access);
                    451: }

unix.superglobalmegacorp.com

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