Annotation of OSKit-Mach/vm/vm_debug.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990 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_debug.c.
        !            28:  *     Author: Rich Draves
        !            29:  *     Date:   March, 1990
        !            30:  *
        !            31:  *     Exported kernel calls.  See mach_debug/mach_debug.defs.
        !            32:  */
        !            33: 
        !            34: #include <mach_vm_debug.h>
        !            35: #if MACH_VM_DEBUG
        !            36: 
        !            37: #include <kern/thread.h>
        !            38: #include <mach/kern_return.h>
        !            39: #include <mach/machine/vm_types.h>
        !            40: #include <mach/memory_object.h>
        !            41: #include <mach/vm_prot.h>
        !            42: #include <mach/vm_inherit.h>
        !            43: #include <mach/vm_param.h>
        !            44: #include <mach_debug/vm_info.h>
        !            45: #include <mach_debug/hash_info.h>
        !            46: #include <vm/vm_map.h>
        !            47: #include <vm/vm_kern.h>
        !            48: #include <vm/vm_object.h>
        !            49: #include <kern/task.h>
        !            50: #include <kern/host.h>
        !            51: #include <ipc/ipc_port.h>
        !            52: 
        !            53: 
        !            54: 
        !            55: /*
        !            56:  *     Routine:        vm_object_real_name
        !            57:  *     Purpose:
        !            58:  *             Convert a VM object to a name port.
        !            59:  *     Conditions:
        !            60:  *             Takes object and port locks.
        !            61:  *     Returns:
        !            62:  *             A naked send right for the object's name port,
        !            63:  *             or IP_NULL if the object or its name port is null.
        !            64:  */
        !            65: 
        !            66: ipc_port_t
        !            67: vm_object_real_name(object)
        !            68:        vm_object_t object;
        !            69: {
        !            70:        ipc_port_t port = IP_NULL;
        !            71: 
        !            72:        if (object != VM_OBJECT_NULL) {
        !            73:                vm_object_lock(object);
        !            74:                if (object->pager_name != IP_NULL)
        !            75:                        port = ipc_port_make_send(object->pager_name);
        !            76:                vm_object_unlock(object);
        !            77:        }
        !            78: 
        !            79:        return port;
        !            80: }
        !            81: 
        !            82: /*
        !            83:  *     Routine:        mach_vm_region_info [kernel call]
        !            84:  *     Purpose:
        !            85:  *             Retrieve information about a VM region,
        !            86:  *             including info about the object chain.
        !            87:  *     Conditions:
        !            88:  *             Nothing locked.
        !            89:  *     Returns:
        !            90:  *             KERN_SUCCESS            Retrieve region/object info.
        !            91:  *             KERN_INVALID_TASK       The map is null.
        !            92:  *             KERN_NO_SPACE           There is no entry at/after the address.
        !            93:  */
        !            94: 
        !            95: kern_return_t
        !            96: mach_vm_region_info(map, address, regionp, portp)
        !            97:        vm_map_t map;
        !            98:        vm_offset_t address;
        !            99:        vm_region_info_t *regionp;
        !           100:        ipc_port_t *portp;
        !           101: {
        !           102:        vm_map_t cmap;          /* current map in traversal */
        !           103:        vm_map_t nmap;          /* next map to look at */
        !           104:        vm_map_entry_t entry;   /* entry in current map */
        !           105:        vm_object_t object;
        !           106: 
        !           107:        if (map == VM_MAP_NULL)
        !           108:                return KERN_INVALID_TASK;
        !           109: 
        !           110:        /* find the entry containing (or following) the address */
        !           111: 
        !           112:        vm_map_lock_read(map);
        !           113:        for (cmap = map;;) {
        !           114:                /* cmap is read-locked */
        !           115: 
        !           116:                if (!vm_map_lookup_entry(cmap, address, &entry)) {
        !           117:                        entry = entry->vme_next;
        !           118:                        if (entry == vm_map_to_entry(cmap)) {
        !           119:                                if (map == cmap) {
        !           120:                                        vm_map_unlock_read(cmap);
        !           121:                                        return KERN_NO_SPACE;
        !           122:                                }
        !           123: 
        !           124:                                /* back out to top-level & skip this submap */
        !           125: 
        !           126:                                address = vm_map_max(cmap);
        !           127:                                vm_map_unlock_read(cmap);
        !           128:                                vm_map_lock_read(map);
        !           129:                                cmap = map;
        !           130:                                continue;
        !           131:                        }
        !           132:                }
        !           133: 
        !           134:                if (entry->is_sub_map) {
        !           135:                        /* move down to the sub map */
        !           136: 
        !           137:                        nmap = entry->object.sub_map;
        !           138:                        vm_map_lock_read(nmap);
        !           139:                        vm_map_unlock_read(cmap);
        !           140:                        cmap = nmap;
        !           141:                        continue;
        !           142:                } else {
        !           143:                        break;
        !           144:                }
        !           145:                /*NOTREACHED*/
        !           146:        }
        !           147: 
        !           148: 
        !           149:        assert(entry->vme_start < entry->vme_end);
        !           150: 
        !           151:        regionp->vri_start = entry->vme_start;
        !           152:        regionp->vri_end = entry->vme_end;
        !           153: 
        !           154:        /* attributes from the real entry */
        !           155: 
        !           156:        regionp->vri_protection = entry->protection;
        !           157:        regionp->vri_max_protection = entry->max_protection;
        !           158:        regionp->vri_inheritance = entry->inheritance;
        !           159:        regionp->vri_wired_count = entry->wired_count;
        !           160:        regionp->vri_user_wired_count = entry->user_wired_count;
        !           161: 
        !           162:        object = entry->object.vm_object;
        !           163:        *portp = vm_object_real_name(object);
        !           164:        regionp->vri_object = (vm_offset_t) object;
        !           165:        regionp->vri_offset = entry->offset;
        !           166:        regionp->vri_needs_copy = entry->needs_copy;
        !           167: 
        !           168:        regionp->vri_sharing = entry->is_shared;
        !           169: 
        !           170:        vm_map_unlock_read(cmap);
        !           171:        return KERN_SUCCESS;
        !           172: }
        !           173: 
        !           174: /*
        !           175:  *     Routine:        mach_vm_object_info [kernel call]
        !           176:  *     Purpose:
        !           177:  *             Retrieve information about a VM object.
        !           178:  *     Conditions:
        !           179:  *             Nothing locked.
        !           180:  *     Returns:
        !           181:  *             KERN_SUCCESS            Retrieved object info.
        !           182:  *             KERN_INVALID_ARGUMENT   The object is null.
        !           183:  */
        !           184: 
        !           185: kern_return_t
        !           186: mach_vm_object_info(object, infop, shadowp, copyp)
        !           187:        vm_object_t object;
        !           188:        vm_object_info_t *infop;
        !           189:        ipc_port_t *shadowp;
        !           190:        ipc_port_t *copyp;
        !           191: {
        !           192:        vm_object_info_t info;
        !           193:        vm_object_info_state_t state;
        !           194:        ipc_port_t shadow, copy;
        !           195: 
        !           196:        if (object == VM_OBJECT_NULL)
        !           197:                return KERN_INVALID_ARGUMENT;
        !           198: 
        !           199:        /*
        !           200:         *      Because of lock-ordering/deadlock considerations,
        !           201:         *      we can't use vm_object_real_name for the copy object.
        !           202:         */
        !           203: 
        !           204:     retry:
        !           205:        vm_object_lock(object);
        !           206:        copy = IP_NULL;
        !           207:        if (object->copy != VM_OBJECT_NULL) {
        !           208:                if (!vm_object_lock_try(object->copy)) {
        !           209:                        vm_object_unlock(object);
        !           210:                        simple_lock_pause();    /* wait a bit */
        !           211:                        goto retry;
        !           212:                }
        !           213: 
        !           214:                if (object->copy->pager_name != IP_NULL)
        !           215:                        copy = ipc_port_make_send(object->copy->pager_name);
        !           216:                vm_object_unlock(object->copy);
        !           217:        }
        !           218:        shadow = vm_object_real_name(object->shadow);
        !           219: 
        !           220:        info.voi_object = (vm_offset_t) object;
        !           221:        info.voi_pagesize = PAGE_SIZE;
        !           222:        info.voi_size = object->size;
        !           223:        info.voi_ref_count = object->ref_count;
        !           224:        info.voi_resident_page_count = object->resident_page_count;
        !           225:        info.voi_absent_count = object->absent_count;
        !           226:        info.voi_copy = (vm_offset_t) object->copy;
        !           227:        info.voi_shadow = (vm_offset_t) object->shadow;
        !           228:        info.voi_shadow_offset = object->shadow_offset;
        !           229:        info.voi_paging_offset = object->paging_offset;
        !           230:        info.voi_copy_strategy = object->copy_strategy;
        !           231:        info.voi_last_alloc = object->last_alloc;
        !           232:        info.voi_paging_in_progress = object->paging_in_progress;
        !           233: 
        !           234:        state = 0;
        !           235:        if (object->pager_created)
        !           236:                state |= VOI_STATE_PAGER_CREATED;
        !           237:        if (object->pager_initialized)
        !           238:                state |= VOI_STATE_PAGER_INITIALIZED;
        !           239:        if (object->pager_ready)
        !           240:                state |= VOI_STATE_PAGER_READY;
        !           241:        if (object->can_persist)
        !           242:                state |= VOI_STATE_CAN_PERSIST;
        !           243:        if (object->internal)
        !           244:                state |= VOI_STATE_INTERNAL;
        !           245:        if (object->temporary)
        !           246:                state |= VOI_STATE_TEMPORARY;
        !           247:        if (object->alive)
        !           248:                state |= VOI_STATE_ALIVE;
        !           249:        if (object->lock_in_progress)
        !           250:                state |= VOI_STATE_LOCK_IN_PROGRESS;
        !           251:        if (object->lock_restart)
        !           252:                state |= VOI_STATE_LOCK_RESTART;
        !           253:        if (object->use_old_pageout)
        !           254:                state |= VOI_STATE_USE_OLD_PAGEOUT;
        !           255:        info.voi_state = state;
        !           256:        vm_object_unlock(object);
        !           257: 
        !           258:        *infop = info;
        !           259:        *shadowp = shadow;
        !           260:        *copyp = copy;
        !           261:        return KERN_SUCCESS;
        !           262: }
        !           263: 
        !           264: #define VPI_STATE_NODATA       (VPI_STATE_BUSY|VPI_STATE_FICTITIOUS| \
        !           265:                                 VPI_STATE_PRIVATE|VPI_STATE_ABSENT)
        !           266: 
        !           267: /*
        !           268:  *     Routine:        mach_vm_object_pages [kernel call]
        !           269:  *     Purpose:
        !           270:  *             Retrieve information about the pages in a VM object.
        !           271:  *     Conditions:
        !           272:  *             Nothing locked.  Obeys CountInOut protocol.
        !           273:  *     Returns:
        !           274:  *             KERN_SUCCESS            Retrieved object info.
        !           275:  *             KERN_INVALID_ARGUMENT   The object is null.
        !           276:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
        !           277:  */
        !           278: 
        !           279: kern_return_t
        !           280: mach_vm_object_pages(object, pagesp, countp)
        !           281:        vm_object_t object;
        !           282:        vm_page_info_array_t *pagesp;
        !           283:        natural_t *countp;
        !           284: {
        !           285:        vm_size_t size;
        !           286:        vm_offset_t addr;
        !           287:        vm_page_info_t *pages;
        !           288:        unsigned int potential, actual, count;
        !           289:        vm_page_t p;
        !           290:        kern_return_t kr;
        !           291: 
        !           292:        if (object == VM_OBJECT_NULL)
        !           293:                return KERN_INVALID_ARGUMENT;
        !           294: 
        !           295:        /* start with in-line memory */
        !           296: 
        !           297:        pages = *pagesp;
        !           298:        potential = *countp;
        !           299: 
        !           300:        for (size = 0;;) {
        !           301:                vm_object_lock(object);
        !           302:                actual = object->resident_page_count;
        !           303:                if (actual <= potential)
        !           304:                        break;
        !           305:                vm_object_unlock(object);
        !           306: 
        !           307:                if (pages != *pagesp)
        !           308:                        kmem_free(ipc_kernel_map, addr, size);
        !           309: 
        !           310:                size = round_page(actual * sizeof *pages);
        !           311:                kr = kmem_alloc(ipc_kernel_map, &addr, size);
        !           312:                if (kr != KERN_SUCCESS)
        !           313:                        return kr;
        !           314: 
        !           315:                pages = (vm_page_info_t *) addr;
        !           316:                potential = size/sizeof *pages;
        !           317:        }
        !           318:        /* object is locked, we have enough wired memory */
        !           319: 
        !           320:        count = 0;
        !           321:        queue_iterate(&object->memq, p, vm_page_t, listq) {
        !           322:                vm_page_info_t *info = &pages[count++];
        !           323:                vm_page_info_state_t state = 0;
        !           324: 
        !           325:                info->vpi_offset = p->offset;
        !           326:                info->vpi_phys_addr = p->phys_addr;
        !           327:                info->vpi_wire_count = p->wire_count;
        !           328:                info->vpi_page_lock = p->page_lock;
        !           329:                info->vpi_unlock_request = p->unlock_request;
        !           330: 
        !           331:                if (p->busy)
        !           332:                        state |= VPI_STATE_BUSY;
        !           333:                if (p->wanted)
        !           334:                        state |= VPI_STATE_WANTED;
        !           335:                if (p->tabled)
        !           336:                        state |= VPI_STATE_TABLED;
        !           337:                if (p->fictitious)
        !           338:                        state |= VPI_STATE_FICTITIOUS;
        !           339:                if (p->private)
        !           340:                        state |= VPI_STATE_PRIVATE;
        !           341:                if (p->absent)
        !           342:                        state |= VPI_STATE_ABSENT;
        !           343:                if (p->error)
        !           344:                        state |= VPI_STATE_ERROR;
        !           345:                if (p->dirty)
        !           346:                        state |= VPI_STATE_DIRTY;
        !           347:                if (p->precious)
        !           348:                        state |= VPI_STATE_PRECIOUS;
        !           349:                if (p->overwriting)
        !           350:                        state |= VPI_STATE_OVERWRITING;
        !           351: 
        !           352:                if (((state & (VPI_STATE_NODATA|VPI_STATE_DIRTY)) == 0) &&
        !           353:                    pmap_is_modified(p->phys_addr)) {
        !           354:                        state |= VPI_STATE_DIRTY;
        !           355:                        p->dirty = TRUE;
        !           356:                }
        !           357: 
        !           358:                vm_page_lock_queues();
        !           359:                if (p->inactive)
        !           360:                        state |= VPI_STATE_INACTIVE;
        !           361:                if (p->active)
        !           362:                        state |= VPI_STATE_ACTIVE;
        !           363:                if (p->laundry)
        !           364:                        state |= VPI_STATE_LAUNDRY;
        !           365:                if (p->free)
        !           366:                        state |= VPI_STATE_FREE;
        !           367:                if (p->reference)
        !           368:                        state |= VPI_STATE_REFERENCE;
        !           369: 
        !           370:                if (((state & (VPI_STATE_NODATA|VPI_STATE_REFERENCE)) == 0) &&
        !           371:                    pmap_is_referenced(p->phys_addr)) {
        !           372:                        state |= VPI_STATE_REFERENCE;
        !           373:                        p->reference = TRUE;
        !           374:                }
        !           375:                vm_page_unlock_queues();
        !           376: 
        !           377:                info->vpi_state = state;
        !           378:        }
        !           379: 
        !           380:        if (object->resident_page_count != count)
        !           381:                panic("mach_vm_object_pages");
        !           382:        vm_object_unlock(object);
        !           383: 
        !           384:        if (pages == *pagesp) {
        !           385:                /* data fit in-line; nothing to deallocate */
        !           386: 
        !           387:                *countp = actual;
        !           388:        } else if (actual == 0) {
        !           389:                kmem_free(ipc_kernel_map, addr, size);
        !           390: 
        !           391:                *countp = 0;
        !           392:        } else {
        !           393:                vm_size_t size_used, rsize_used;
        !           394:                vm_map_copy_t copy;
        !           395: 
        !           396:                /* kmem_alloc doesn't zero memory */
        !           397: 
        !           398:                size_used = actual * sizeof *pages;
        !           399:                rsize_used = round_page(size_used);
        !           400: 
        !           401:                if (rsize_used != size)
        !           402:                        kmem_free(ipc_kernel_map,
        !           403:                                  addr + rsize_used, size - rsize_used);
        !           404: 
        !           405:                if (size_used != rsize_used)
        !           406:                        bzero((char *) (addr + size_used),
        !           407:                              rsize_used - size_used);
        !           408: 
        !           409:                kr = vm_map_copyin(ipc_kernel_map, addr, rsize_used,
        !           410:                                   TRUE, &copy);
        !           411:                assert(kr == KERN_SUCCESS);
        !           412: 
        !           413:                *pagesp = (vm_page_info_t *) copy;
        !           414:                *countp = actual;
        !           415:        }
        !           416: 
        !           417:        return KERN_SUCCESS;
        !           418: }
        !           419: 
        !           420: #endif /* MACH_VM_DEBUG */
        !           421: 
        !           422: /*
        !           423:  *     Routine:        host_virtual_physical_table_info
        !           424:  *     Purpose:
        !           425:  *             Return information about the VP table.
        !           426:  *     Conditions:
        !           427:  *             Nothing locked.  Obeys CountInOut protocol.
        !           428:  *     Returns:
        !           429:  *             KERN_SUCCESS            Returned information.
        !           430:  *             KERN_INVALID_HOST       The host is null.
        !           431:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
        !           432:  */
        !           433: 
        !           434: kern_return_t
        !           435: host_virtual_physical_table_info(host, infop, countp)
        !           436:        host_t host;
        !           437:        hash_info_bucket_array_t *infop;
        !           438:        natural_t *countp;
        !           439: {
        !           440:        vm_offset_t addr;
        !           441:        vm_size_t size = 0;/* '=0' to quiet gcc warnings */
        !           442:        hash_info_bucket_t *info;
        !           443:        unsigned int potential, actual;
        !           444:        kern_return_t kr;
        !           445: 
        !           446:        if (host == HOST_NULL)
        !           447:                return KERN_INVALID_HOST;
        !           448: 
        !           449:        /* start with in-line data */
        !           450: 
        !           451:        info = *infop;
        !           452:        potential = *countp;
        !           453: 
        !           454:        for (;;) {
        !           455:                actual = vm_page_info(info, potential);
        !           456:                if (actual <= potential)
        !           457:                        break;
        !           458: 
        !           459:                /* allocate more memory */
        !           460: 
        !           461:                if (info != *infop)
        !           462:                        kmem_free(ipc_kernel_map, addr, size);
        !           463: 
        !           464:                size = round_page(actual * sizeof *info);
        !           465:                kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size);
        !           466:                if (kr != KERN_SUCCESS)
        !           467:                        return KERN_RESOURCE_SHORTAGE;
        !           468: 
        !           469:                info = (hash_info_bucket_t *) addr;
        !           470:                potential = size/sizeof *info;
        !           471:        }
        !           472: 
        !           473:        if (info == *infop) {
        !           474:                /* data fit in-line; nothing to deallocate */
        !           475: 
        !           476:                *countp = actual;
        !           477:        } else if (actual == 0) {
        !           478:                kmem_free(ipc_kernel_map, addr, size);
        !           479: 
        !           480:                *countp = 0;
        !           481:        } else {
        !           482:                vm_map_copy_t copy;
        !           483:                vm_size_t used;
        !           484: 
        !           485:                used = round_page(actual * sizeof *info);
        !           486: 
        !           487:                if (used != size)
        !           488:                        kmem_free(ipc_kernel_map, addr + used, size - used);
        !           489: 
        !           490:                kr = vm_map_copyin(ipc_kernel_map, addr, used,
        !           491:                                   TRUE, &copy);
        !           492:                assert(kr == KERN_SUCCESS);
        !           493: 
        !           494:                *infop = (hash_info_bucket_t *) copy;
        !           495:                *countp = actual;
        !           496:        }
        !           497: 
        !           498:        return KERN_SUCCESS;
        !           499: }

unix.superglobalmegacorp.com

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