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

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:  */
                     59: kern_return_t vm_allocate(map, addr, size, anywhere)
                     60:        register vm_map_t       map;
                     61:        register vm_offset_t    *addr;
                     62:        register vm_size_t      size;
                     63:        boolean_t               anywhere;
                     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:  */
                    100: kern_return_t vm_deallocate(map, start, size)
                    101:        register vm_map_t       map;
                    102:        vm_offset_t             start;
                    103:        vm_size_t               size;
                    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:  */
                    118: kern_return_t vm_inherit(map, start, size, new_inheritance)
                    119:        register vm_map_t       map;
                    120:        vm_offset_t             start;
                    121:        vm_size_t               size;
                    122:        vm_inherit_t            new_inheritance;
                    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: 
                    152: kern_return_t vm_protect(map, start, size, set_maximum, new_protection)
                    153:        register 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;
                    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: 
                    175: kern_return_t vm_statistics(map, stat)
                    176:        vm_map_t        map;
                    177:        vm_statistics_data_t    *stat;
                    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:  */
                    220: kern_return_t vm_machine_attribute(map, address, size, attribute, value)
                    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 */
                    226: {
                    227:        extern kern_return_t    vm_map_machine_attribute();
                    228: 
                    229:        if (map == VM_MAP_NULL)
                    230:                return(KERN_INVALID_ARGUMENT);
                    231: 
                    232:        /*Check if range includes projected buffer;
                    233:          user is not allowed direct manipulation in that case*/
                    234:        if (projected_buffer_in_range(map, address, address+size))
                    235:                return(KERN_INVALID_ARGUMENT);
                    236: 
                    237:        return vm_map_machine_attribute(map, address, size, attribute, value);
                    238: }
                    239: 
                    240: kern_return_t vm_read(map, address, size, data, data_size)
                    241:        vm_map_t        map;
                    242:        vm_address_t    address;
                    243:        vm_size_t       size;
                    244:        pointer_t       *data;
                    245:        vm_size_t       *data_size;
                    246: {
                    247:        kern_return_t   error;
                    248:        vm_map_copy_t   ipc_address;
                    249: 
                    250:        if (map == VM_MAP_NULL)
                    251:                return(KERN_INVALID_ARGUMENT);
                    252: 
                    253:        if ((error = vm_map_copyin(map,
                    254:                                address,
                    255:                                size,
                    256:                                FALSE,  /* src_destroy */
                    257:                                &ipc_address)) == KERN_SUCCESS) {
                    258:                *data = (pointer_t) ipc_address;
                    259:                *data_size = size;
                    260:        }
                    261:        return(error);
                    262: }
                    263: 
                    264: kern_return_t vm_write(map, address, data, size)
                    265:        vm_map_t        map;
                    266:        vm_address_t    address;
                    267:        pointer_t       data;
                    268:        vm_size_t       size;
                    269: {
                    270:        if (map == VM_MAP_NULL)
                    271:                return KERN_INVALID_ARGUMENT;
                    272: 
                    273:        return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data,
                    274:                                     FALSE /* interruptible XXX */);
                    275: }
                    276: 
                    277: kern_return_t vm_copy(map, source_address, size, dest_address)
                    278:        vm_map_t        map;
                    279:        vm_address_t    source_address;
                    280:        vm_size_t       size;
                    281:        vm_address_t    dest_address;
                    282: {
                    283:        vm_map_copy_t copy;
                    284:        kern_return_t kr;
                    285: 
                    286:        if (map == VM_MAP_NULL)
                    287:                return KERN_INVALID_ARGUMENT;
                    288: 
                    289:        kr = vm_map_copyin(map, source_address, size,
                    290:                           FALSE, &copy);
                    291:        if (kr != KERN_SUCCESS)
                    292:                return kr;
                    293: 
                    294:        kr = vm_map_copy_overwrite(map, dest_address, copy,
                    295:                                   FALSE /* interruptible XXX */);
                    296:        if (kr != KERN_SUCCESS) {
                    297:                vm_map_copy_discard(copy);
                    298:                return kr;
                    299:        }
                    300: 
                    301:        return KERN_SUCCESS;
                    302: }
                    303: 
1.1.1.2 ! root      304: 
1.1       root      305: /*
                    306:  *     Routine:        vm_map
                    307:  */
                    308: kern_return_t vm_map(
                    309:                target_map,
                    310:                address, size, mask, anywhere,
                    311:                memory_object, offset,
                    312:                copy,
                    313:                cur_protection, max_protection, inheritance)
                    314:        vm_map_t        target_map;
                    315:        vm_offset_t     *address;
                    316:        vm_size_t       size;
                    317:        vm_offset_t     mask;
                    318:        boolean_t       anywhere;
                    319:        ipc_port_t      memory_object;
                    320:        vm_offset_t     offset;
                    321:        boolean_t       copy;
                    322:        vm_prot_t       cur_protection;
                    323:        vm_prot_t       max_protection;
                    324:        vm_inherit_t    inheritance;
                    325: {
                    326:        register
                    327:        vm_object_t     object;
                    328:        register
                    329:        kern_return_t   result;
                    330: 
                    331:        if ((target_map == VM_MAP_NULL) ||
                    332:            (cur_protection & ~VM_PROT_ALL) ||
                    333:            (max_protection & ~VM_PROT_ALL))
                    334:                return(KERN_INVALID_ARGUMENT);
                    335: 
                    336:         switch (inheritance) {
                    337:         case VM_INHERIT_NONE:
                    338:         case VM_INHERIT_COPY:
                    339:         case VM_INHERIT_SHARE:
                    340:                 break;
                    341:         default:
                    342:                 return(KERN_INVALID_ARGUMENT);
                    343:         }
                    344: 
1.1.1.2 ! root      345:        if (size == 0)
        !           346:                return KERN_INVALID_ARGUMENT;
        !           347: 
1.1       root      348:        *address = trunc_page(*address);
                    349:        size = round_page(size);
                    350: 
                    351:        if (!IP_VALID(memory_object)) {
                    352:                object = VM_OBJECT_NULL;
                    353:                offset = 0;
                    354:                copy = FALSE;
                    355:        } else if ((object = vm_object_enter(memory_object, size, FALSE))
                    356:                        == VM_OBJECT_NULL)
1.1.1.2 ! root      357:          {
        !           358:            ipc_port_t real_memobj;
        !           359:            vm_prot_t prot;
        !           360:            result = memory_object_proxy_lookup (memory_object, &real_memobj,
        !           361:                                                 &prot);
        !           362:            if (result != KERN_SUCCESS)
        !           363:              return result;
        !           364: 
        !           365:            /* Reduce the allowed access to the memory object.  */
        !           366:            max_protection &= prot;
        !           367:            cur_protection &= prot;
        !           368: 
        !           369:            if ((object = vm_object_enter(real_memobj, size, FALSE))
        !           370:                == VM_OBJECT_NULL)
        !           371:              return KERN_INVALID_ARGUMENT;
        !           372:          }
1.1       root      373: 
                    374:        /*
                    375:         *      Perform the copy if requested
                    376:         */
                    377: 
                    378:        if (copy) {
                    379:                vm_object_t     new_object;
                    380:                vm_offset_t     new_offset;
                    381: 
                    382:                result = vm_object_copy_strategically(object, offset, size,
                    383:                                &new_object, &new_offset,
                    384:                                &copy);
                    385: 
                    386:                /*
                    387:                 *      Throw away the reference to the
                    388:                 *      original object, as it won't be mapped.
                    389:                 */
                    390: 
                    391:                vm_object_deallocate(object);
                    392: 
                    393:                if (result != KERN_SUCCESS)
                    394:                        return (result);
                    395: 
                    396:                object = new_object;
                    397:                offset = new_offset;
                    398:        }
                    399: 
                    400:        if ((result = vm_map_enter(target_map,
                    401:                                address, size, mask, anywhere,
                    402:                                object, offset,
                    403:                                copy,
                    404:                                cur_protection, max_protection, inheritance
                    405:                                )) != KERN_SUCCESS)
                    406:                vm_object_deallocate(object);
                    407:        return(result);
                    408: }
                    409: 
                    410: /*
                    411:  *     Specify that the range of the virtual address space
                    412:  *     of the target task must not cause page faults for
                    413:  *     the indicated accesses.
                    414:  *
                    415:  *     [ To unwire the pages, specify VM_PROT_NONE. ]
                    416:  */
                    417: kern_return_t vm_wire(host, map, start, size, access)
                    418:        host_t                  host;
                    419:        register vm_map_t       map;
                    420:        vm_offset_t             start;
                    421:        vm_size_t               size;
                    422:        vm_prot_t               access;
                    423: {
                    424:        if (host == HOST_NULL)
                    425:                return KERN_INVALID_HOST;
                    426: 
                    427:        if (map == VM_MAP_NULL)
                    428:                return KERN_INVALID_TASK;
                    429: 
                    430:        if (access & ~VM_PROT_ALL)
                    431:                return KERN_INVALID_ARGUMENT;
                    432: 
                    433:        /*Check if range includes projected buffer;
                    434:          user is not allowed direct manipulation in that case*/
                    435:        if (projected_buffer_in_range(map, start, start+size))
                    436:                return(KERN_INVALID_ARGUMENT);
                    437: 
                    438:        return vm_map_pageable_user(map,
                    439:                                    trunc_page(start),
                    440:                                    round_page(start+size),
                    441:                                    access);
                    442: }

unix.superglobalmegacorp.com

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