Annotation of OSKit-Mach/vm/vm_debug.c, revision 1.1.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.