Annotation of Gnu-Mach/vm/vm_debug.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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