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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990 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_debug.c.
                     54:  *     Author: Rich Draves
                     55:  *     Date:   March, 1990
                     56:  *
                     57:  *     Exported kernel calls.  See mach_debug/mach_debug.defs.
                     58:  */
                     59: #include <mach_vm_debug.h>
                     60: #include <mach/kern_return.h>
                     61: #include <mach/mach_host_server.h>
                     62: #include <mach/vm_task_server.h>
                     63: #include <mach_debug/vm_info.h>
                     64: #include <mach_debug/page_info.h>
                     65: #include <mach_debug/hash_info.h>
                     66: 
                     67: #if MACH_VM_DEBUG
                     68: #include <mach/machine/vm_types.h>
                     69: #include <mach/memory_object_types.h>
                     70: #include <mach/vm_prot.h>
                     71: #include <mach/vm_inherit.h>
                     72: #include <mach/vm_param.h>
                     73: #include <kern/thread.h>
                     74: #include <vm/vm_map.h>
                     75: #include <vm/vm_kern.h>
                     76: #include <vm/vm_object.h>
                     77: #include <kern/task.h>
                     78: #include <kern/host.h>
                     79: #include <ipc/ipc_port.h>
                     80: #include <vm/vm_debug.h>
                     81: #endif
                     82: 
                     83: /*
                     84:  *     Routine:        mach_vm_region_info [kernel call]
                     85:  *     Purpose:
                     86:  *             Retrieve information about a VM region,
                     87:  *             including info about the object chain.
                     88:  *     Conditions:
                     89:  *             Nothing locked.
                     90:  *     Returns:
                     91:  *             KERN_SUCCESS            Retrieve region/object info.
                     92:  *             KERN_INVALID_TASK       The map is null.
                     93:  *             KERN_NO_SPACE           There is no entry at/after the address.
                     94:  *             KERN_RESOURCE_SHORTAGE  Can't allocate memory.
                     95:  */
                     96: 
                     97: kern_return_t
                     98: mach_vm_region_info(
                     99:        vm_map_t                map,
                    100:        vm_offset_t             address,
                    101:        vm_info_region_t        *regionp,
                    102:        vm_info_object_array_t  *objectsp,
                    103:        mach_msg_type_number_t  *objectsCntp)
                    104: {
                    105: #if !MACH_VM_DEBUG
                    106:         return KERN_FAILURE;
                    107: #else
                    108:        vm_map_copy_t copy;
                    109:        vm_offset_t addr;       /* memory for OOL data */
                    110:        vm_size_t size;         /* size of the memory */
                    111:        unsigned int room;      /* room for this many objects */
                    112:        unsigned int used;      /* actually this many objects */
                    113:        vm_info_region_t region;
                    114:        kern_return_t kr;
                    115: 
                    116:        if (map == VM_MAP_NULL)
                    117:                return KERN_INVALID_TASK;
                    118: 
                    119:        size = 0;               /* no memory allocated yet */
                    120: 
                    121:        for (;;) {
                    122:                vm_map_t cmap;  /* current map in traversal */
                    123:                vm_map_t nmap;  /* next map to look at */
                    124:                vm_map_entry_t entry;
                    125:                vm_object_t object, cobject, nobject;
                    126: 
                    127:                /* nothing is locked */
                    128: 
                    129:                vm_map_lock_read(map);
                    130:                for (cmap = map;; cmap = nmap) {
                    131:                        /* cmap is read-locked */
                    132: 
                    133:                        if (!vm_map_lookup_entry(cmap, address, &entry)) {
                    134:                                entry = entry->vme_next;
                    135:                                if (entry == vm_map_to_entry(cmap)) {
                    136:                                        vm_map_unlock_read(cmap);
                    137:                                        if (size != 0)
                    138:                                                kmem_free(ipc_kernel_map,
                    139:                                                          addr, size);
                    140:                                        return KERN_NO_SPACE;
                    141:                                }
                    142:                        }
                    143: 
                    144:                        if (entry->is_sub_map)
                    145:                                nmap = entry->object.sub_map;
                    146:                        else
                    147:                                break;
                    148: 
                    149:                        /* move down to the lower map */
                    150: 
                    151:                        vm_map_lock_read(nmap);
                    152:                        vm_map_unlock_read(cmap);
                    153:                }
                    154: 
                    155:                /* cmap is read-locked; we have a real entry */
                    156: 
                    157:                object = entry->object.vm_object;
                    158:                region.vir_start = entry->vme_start;
                    159:                region.vir_end = entry->vme_end;
                    160:                region.vir_object = (vm_offset_t) object;
                    161:                region.vir_offset = entry->offset;
                    162:                region.vir_needs_copy = entry->needs_copy;
                    163:                region.vir_protection = entry->protection;
                    164:                region.vir_max_protection = entry->max_protection;
                    165:                region.vir_inheritance = entry->inheritance;
                    166:                region.vir_wired_count = entry->wired_count;
                    167:                region.vir_user_wired_count = entry->user_wired_count;
                    168: 
                    169:                used = 0;
                    170:                room = size / sizeof(vm_info_object_t);
                    171: 
                    172:                if (object == VM_OBJECT_NULL) {
                    173:                        vm_map_unlock_read(cmap);
                    174:                        /* no memory needed */
                    175:                        break;
                    176:                }
                    177: 
                    178:                vm_object_lock(object);
                    179:                vm_map_unlock_read(cmap);
                    180: 
                    181:                for (cobject = object;; cobject = nobject) {
                    182:                        /* cobject is locked */
                    183: 
                    184:                        if (used < room) {
                    185:                                vm_info_object_t *vio =
                    186:                                        &((vm_info_object_t *) addr)[used];
                    187: 
                    188:                                vio->vio_object =
                    189:                                        (vm_offset_t) cobject;
                    190:                                vio->vio_size =
                    191:                                        cobject->size;
                    192:                                vio->vio_ref_count =
                    193:                                        cobject->ref_count;
                    194:                                vio->vio_resident_page_count =
                    195:                                        cobject->resident_page_count;
                    196:                                vio->vio_absent_count =
                    197:                                        cobject->absent_count;
                    198:                                vio->vio_copy =
                    199:                                        (vm_offset_t) cobject->copy;
                    200:                                vio->vio_shadow =
                    201:                                        (vm_offset_t) cobject->shadow;
                    202:                                vio->vio_shadow_offset =
                    203:                                        cobject->shadow_offset;
                    204:                                vio->vio_paging_offset =
                    205:                                        cobject->paging_offset;
                    206:                                vio->vio_copy_strategy =
                    207:                                        cobject->copy_strategy;
                    208:                                vio->vio_last_alloc =
                    209:                                        cobject->last_alloc;
                    210:                                vio->vio_paging_in_progress =
                    211:                                        cobject->paging_in_progress;
                    212:                                vio->vio_pager_created =
                    213:                                        cobject->pager_created;
                    214:                                vio->vio_pager_initialized =
                    215:                                        cobject->pager_initialized;
                    216:                                vio->vio_pager_ready =
                    217:                                        cobject->pager_ready;
                    218:                                vio->vio_can_persist =
                    219:                                        cobject->can_persist;
                    220:                                vio->vio_internal =
                    221:                                        cobject->internal;
                    222:                                vio->vio_temporary =
                    223:                                        cobject->temporary;
                    224:                                vio->vio_alive =
                    225:                                        cobject->alive;
                    226:                                vio->vio_lock_in_progress =
                    227:                                        cobject->lock_in_progress;
                    228:                                vio->vio_lock_restart =
                    229:                                        cobject->lock_restart;
                    230:                        }
                    231: 
                    232:                        used++;
                    233:                        nobject = cobject->shadow;
                    234:                        if (nobject == VM_OBJECT_NULL) {
                    235:                                vm_object_unlock(cobject);
                    236:                                break;
                    237:                        }
                    238: 
                    239:                        vm_object_lock(nobject);
                    240:                        vm_object_unlock(cobject);
                    241:                }
                    242: 
                    243:                /* nothing locked */
                    244: 
                    245:                if (used <= room)
                    246:                        break;
                    247: 
                    248:                /* must allocate more memory */
                    249: 
                    250:                if (size != 0)
                    251:                        kmem_free(ipc_kernel_map, addr, size);
                    252:                size = round_page(2 * used * sizeof(vm_info_object_t));
                    253: 
                    254:                kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE);
                    255:                if (kr != KERN_SUCCESS)
                    256:                        return KERN_RESOURCE_SHORTAGE;
                    257: 
                    258:                kr = vm_map_wire(ipc_kernel_map, addr, addr + size,
                    259:                                     VM_PROT_READ|VM_PROT_WRITE, FALSE);
                    260:                assert(kr == KERN_SUCCESS);
                    261:        }
                    262: 
                    263:        /* free excess memory; make remaining memory pageable */
                    264: 
                    265:        if (used == 0) {
                    266:                copy = VM_MAP_COPY_NULL;
                    267: 
                    268:                if (size != 0)
                    269:                        kmem_free(ipc_kernel_map, addr, size);
                    270:        } else {
                    271:                vm_size_t size_used =
                    272:                        round_page(used * sizeof(vm_info_object_t));
                    273: 
                    274:                kr = vm_map_unwire(ipc_kernel_map, addr, addr + size_used, FALSE);
                    275:                assert(kr == KERN_SUCCESS);
                    276: 
                    277:                kr = vm_map_copyin(ipc_kernel_map, addr, size_used,
                    278:                                   TRUE, &copy);
                    279:                assert(kr == KERN_SUCCESS);
                    280: 
                    281:                if (size != size_used)
                    282:                        kmem_free(ipc_kernel_map,
                    283:                                  addr + size_used, size - size_used);
                    284:        }
                    285: 
                    286:        *regionp = region;
                    287:        *objectsp = (vm_info_object_array_t) copy;
                    288:        *objectsCntp = used;
                    289:        return KERN_SUCCESS;
                    290: #endif /* MACH_VM_DEBUG */
                    291: }
                    292: 
                    293: /*
                    294:  * Return an array of virtual pages that are mapped to a task.
                    295:  */
                    296: kern_return_t
                    297: vm_mapped_pages_info(
                    298:        vm_map_t                map,
                    299:        page_address_array_t    *pages,
                    300:        mach_msg_type_number_t  *pages_count)
                    301: {
                    302: #if !MACH_VM_DEBUG
                    303:         return KERN_FAILURE;
                    304: #else
                    305:        pmap_t          pmap;
                    306:        vm_size_t       size, size_used;
                    307:        unsigned int    actual, space;
                    308:        page_address_array_t list;
                    309:        vm_offset_t     addr;
                    310: 
                    311:        if (map == VM_MAP_NULL)
                    312:            return (KERN_INVALID_ARGUMENT);
                    313: 
                    314:        pmap = map->pmap;
                    315:        size = pmap_resident_count(pmap) * sizeof(vm_offset_t);
                    316:        size = round_page(size);
                    317: 
                    318:        for (;;) {
                    319:            (void) vm_allocate(ipc_kernel_map, &addr, size, TRUE);
                    320:            (void) vm_map_unwire(ipc_kernel_map, addr, addr + size, FALSE);
                    321: 
                    322:            list = (page_address_array_t) addr;
                    323:            space = size / sizeof(vm_offset_t);
                    324: 
                    325:            actual = pmap_list_resident_pages(pmap,
                    326:                                        list,
                    327:                                        space);
                    328:            if (actual <= space)
                    329:                break;
                    330: 
                    331:            /*
                    332:             * Free memory if not enough
                    333:             */
                    334:            (void) kmem_free(ipc_kernel_map, addr, size);
                    335: 
                    336:            /*
                    337:             * Try again, doubling the size
                    338:             */
                    339:            size = round_page(actual * sizeof(vm_offset_t));
                    340:        }
                    341:        if (actual == 0) {
                    342:            *pages = 0;
                    343:            *pages_count = 0;
                    344:            (void) kmem_free(ipc_kernel_map, addr, size);
                    345:        }
                    346:        else {
                    347:            *pages_count = actual;
                    348:            size_used = round_page(actual * sizeof(vm_offset_t));
                    349:            (void) vm_map_wire(ipc_kernel_map,
                    350:                                addr, addr + size, 
                    351:                                VM_PROT_READ|VM_PROT_WRITE, FALSE);
                    352:            (void) vm_map_copyin(
                    353:                                ipc_kernel_map,
                    354:                                addr,
                    355:                                size_used,
                    356:                                TRUE,
                    357:                                (vm_map_copy_t *)pages);
                    358:            if (size_used != size) {
                    359:                (void) kmem_free(ipc_kernel_map,
                    360:                                addr + size_used,
                    361:                                size - size_used);
                    362:            }
                    363:        }
                    364: 
                    365:        return (KERN_SUCCESS);
                    366: #endif /* MACH_VM_DEBUG */
                    367: }
                    368: 
                    369: /*
                    370:  *     Routine:        host_virtual_physical_table_info
                    371:  *     Purpose:
                    372:  *             Return information about the VP table.
                    373:  *     Conditions:
                    374:  *             Nothing locked.  Obeys CountInOut protocol.
                    375:  *     Returns:
                    376:  *             KERN_SUCCESS            Returned information.
                    377:  *             KERN_INVALID_HOST       The host is null.
                    378:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    379:  */
                    380: 
                    381: kern_return_t
                    382: host_virtual_physical_table_info(
                    383:        host_t                          host,
                    384:        hash_info_bucket_array_t        *infop,
                    385:        mach_msg_type_number_t          *countp)
                    386: {
                    387: #if !MACH_VM_DEBUG
                    388:         return KERN_FAILURE;
                    389: #else
                    390:        vm_offset_t addr;
                    391:        vm_size_t size;
                    392:        hash_info_bucket_t *info;
                    393:        unsigned int potential, actual;
                    394:        kern_return_t kr;
                    395: 
                    396:        if (host == HOST_NULL)
                    397:                return KERN_INVALID_HOST;
                    398: 
                    399:        /* start with in-line data */
                    400: 
                    401:        info = *infop;
                    402:        potential = *countp;
                    403: 
                    404:        for (;;) {
                    405:                actual = vm_page_info(info, potential);
                    406:                if (actual <= potential)
                    407:                        break;
                    408: 
                    409:                /* allocate more memory */
                    410: 
                    411:                if (info != *infop)
                    412:                        kmem_free(ipc_kernel_map, addr, size);
                    413: 
                    414:                size = round_page(actual * sizeof *info);
                    415:                kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size);
                    416:                if (kr != KERN_SUCCESS)
                    417:                        return KERN_RESOURCE_SHORTAGE;
                    418: 
                    419:                info = (hash_info_bucket_t *) addr;
                    420:                potential = size/sizeof *info;
                    421:        }
                    422: 
                    423:        if (info == *infop) {
                    424:                /* data fit in-line; nothing to deallocate */
                    425: 
                    426:                *countp = actual;
                    427:        } else if (actual == 0) {
                    428:                kmem_free(ipc_kernel_map, addr, size);
                    429: 
                    430:                *countp = 0;
                    431:        } else {
                    432:                vm_map_copy_t copy;
                    433:                vm_size_t used;
                    434: 
                    435:                used = round_page(actual * sizeof *info);
                    436: 
                    437:                if (used != size)
                    438:                        kmem_free(ipc_kernel_map, addr + used, size - used);
                    439: 
                    440:                kr = vm_map_copyin(ipc_kernel_map, addr, used,
                    441:                                   TRUE, &copy);
                    442:                assert(kr == KERN_SUCCESS);
                    443: 
                    444:                *infop = (hash_info_bucket_t *) copy;
                    445:                *countp = actual;
                    446:        }
                    447: 
                    448:        return KERN_SUCCESS;
                    449: #endif /* MACH_VM_DEBUG */
                    450: }

unix.superglobalmegacorp.com

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