Annotation of XNU/osfmk/vm/vm_debug.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 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.