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

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
1.1.1.4   root       68: vm_object_real_name(vm_object_t object)
1.1       root       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
1.1.1.4   root       96: mach_vm_region_info(
                     97:        vm_map_t                map,
                     98:        vm_offset_t             address,
                     99:        vm_region_info_t        *regionp,
                    100:        ipc_port_t              *portp)
1.1       root      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
1.1.1.4   root      186: mach_vm_object_info(
                    187:        vm_object_t             object,
                    188:        vm_object_info_t        *infop,
                    189:        ipc_port_t              *shadowp,
                    190:        ipc_port_t              *copyp)
1.1       root      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:        info.voi_state = state;
                    254:        vm_object_unlock(object);
                    255: 
                    256:        *infop = info;
                    257:        *shadowp = shadow;
                    258:        *copyp = copy;
                    259:        return KERN_SUCCESS;
                    260: }
                    261: 
                    262: #define VPI_STATE_NODATA       (VPI_STATE_BUSY|VPI_STATE_FICTITIOUS| \
                    263:                                 VPI_STATE_PRIVATE|VPI_STATE_ABSENT)
                    264: 
                    265: /*
                    266:  *     Routine:        mach_vm_object_pages [kernel call]
                    267:  *     Purpose:
                    268:  *             Retrieve information about the pages in a VM object.
                    269:  *     Conditions:
                    270:  *             Nothing locked.  Obeys CountInOut protocol.
                    271:  *     Returns:
                    272:  *             KERN_SUCCESS            Retrieved object info.
                    273:  *             KERN_INVALID_ARGUMENT   The object is null.
                    274:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    275:  */
                    276: 
                    277: kern_return_t
1.1.1.4   root      278: mach_vm_object_pages(
                    279:        vm_object_t             object,
                    280:        vm_page_info_array_t    *pagesp,
                    281:        natural_t               *countp)
1.1       root      282: {
                    283:        vm_size_t size;
                    284:        vm_offset_t addr;
                    285:        vm_page_info_t *pages;
                    286:        unsigned int potential, actual, count;
                    287:        vm_page_t p;
                    288:        kern_return_t kr;
                    289: 
                    290:        if (object == VM_OBJECT_NULL)
                    291:                return KERN_INVALID_ARGUMENT;
                    292: 
                    293:        /* start with in-line memory */
                    294: 
                    295:        pages = *pagesp;
                    296:        potential = *countp;
                    297: 
                    298:        for (size = 0;;) {
                    299:                vm_object_lock(object);
                    300:                actual = object->resident_page_count;
                    301:                if (actual <= potential)
                    302:                        break;
                    303:                vm_object_unlock(object);
                    304: 
                    305:                if (pages != *pagesp)
                    306:                        kmem_free(ipc_kernel_map, addr, size);
                    307: 
                    308:                size = round_page(actual * sizeof *pages);
                    309:                kr = kmem_alloc(ipc_kernel_map, &addr, size);
                    310:                if (kr != KERN_SUCCESS)
                    311:                        return kr;
                    312: 
                    313:                pages = (vm_page_info_t *) addr;
                    314:                potential = size/sizeof *pages;
                    315:        }
                    316:        /* object is locked, we have enough wired memory */
                    317: 
                    318:        count = 0;
                    319:        queue_iterate(&object->memq, p, vm_page_t, listq) {
                    320:                vm_page_info_t *info = &pages[count++];
                    321:                vm_page_info_state_t state = 0;
                    322: 
                    323:                info->vpi_offset = p->offset;
                    324:                info->vpi_phys_addr = p->phys_addr;
                    325:                info->vpi_wire_count = p->wire_count;
                    326:                info->vpi_page_lock = p->page_lock;
                    327:                info->vpi_unlock_request = p->unlock_request;
                    328: 
                    329:                if (p->busy)
                    330:                        state |= VPI_STATE_BUSY;
                    331:                if (p->wanted)
                    332:                        state |= VPI_STATE_WANTED;
                    333:                if (p->tabled)
                    334:                        state |= VPI_STATE_TABLED;
                    335:                if (p->fictitious)
                    336:                        state |= VPI_STATE_FICTITIOUS;
                    337:                if (p->private)
                    338:                        state |= VPI_STATE_PRIVATE;
                    339:                if (p->absent)
                    340:                        state |= VPI_STATE_ABSENT;
                    341:                if (p->error)
                    342:                        state |= VPI_STATE_ERROR;
                    343:                if (p->dirty)
                    344:                        state |= VPI_STATE_DIRTY;
                    345:                if (p->precious)
                    346:                        state |= VPI_STATE_PRECIOUS;
                    347:                if (p->overwriting)
                    348:                        state |= VPI_STATE_OVERWRITING;
                    349: 
                    350:                if (((state & (VPI_STATE_NODATA|VPI_STATE_DIRTY)) == 0) &&
                    351:                    pmap_is_modified(p->phys_addr)) {
                    352:                        state |= VPI_STATE_DIRTY;
                    353:                        p->dirty = TRUE;
                    354:                }
                    355: 
                    356:                vm_page_lock_queues();
                    357:                if (p->inactive)
                    358:                        state |= VPI_STATE_INACTIVE;
                    359:                if (p->active)
                    360:                        state |= VPI_STATE_ACTIVE;
                    361:                if (p->laundry)
                    362:                        state |= VPI_STATE_LAUNDRY;
                    363:                if (p->free)
                    364:                        state |= VPI_STATE_FREE;
                    365:                if (p->reference)
                    366:                        state |= VPI_STATE_REFERENCE;
                    367: 
                    368:                if (((state & (VPI_STATE_NODATA|VPI_STATE_REFERENCE)) == 0) &&
                    369:                    pmap_is_referenced(p->phys_addr)) {
                    370:                        state |= VPI_STATE_REFERENCE;
                    371:                        p->reference = TRUE;
                    372:                }
                    373:                vm_page_unlock_queues();
                    374: 
                    375:                info->vpi_state = state;
                    376:        }
                    377: 
                    378:        if (object->resident_page_count != count)
                    379:                panic("mach_vm_object_pages");
                    380:        vm_object_unlock(object);
                    381: 
                    382:        if (pages == *pagesp) {
                    383:                /* data fit in-line; nothing to deallocate */
                    384: 
                    385:                *countp = actual;
                    386:        } else if (actual == 0) {
                    387:                kmem_free(ipc_kernel_map, addr, size);
                    388: 
                    389:                *countp = 0;
                    390:        } else {
                    391:                vm_size_t size_used, rsize_used;
                    392:                vm_map_copy_t copy;
                    393: 
                    394:                /* kmem_alloc doesn't zero memory */
                    395: 
                    396:                size_used = actual * sizeof *pages;
                    397:                rsize_used = round_page(size_used);
                    398: 
                    399:                if (rsize_used != size)
                    400:                        kmem_free(ipc_kernel_map,
                    401:                                  addr + rsize_used, size - rsize_used);
                    402: 
                    403:                if (size_used != rsize_used)
1.1.1.4   root      404:                        memset((void *) (addr + size_used), 0,
1.1.1.3   root      405:                               rsize_used - size_used);
1.1       root      406: 
                    407:                kr = vm_map_copyin(ipc_kernel_map, addr, rsize_used,
                    408:                                   TRUE, &copy);
                    409:                assert(kr == KERN_SUCCESS);
                    410: 
                    411:                *pagesp = (vm_page_info_t *) copy;
                    412:                *countp = actual;
                    413:        }
                    414: 
                    415:        return KERN_SUCCESS;
                    416: }
                    417: 
1.1.1.2   root      418: #endif /* MACH_VM_DEBUG */
1.1       root      419: 
                    420: /*
                    421:  *     Routine:        host_virtual_physical_table_info
                    422:  *     Purpose:
                    423:  *             Return information about the VP table.
                    424:  *     Conditions:
                    425:  *             Nothing locked.  Obeys CountInOut protocol.
                    426:  *     Returns:
                    427:  *             KERN_SUCCESS            Returned information.
                    428:  *             KERN_INVALID_HOST       The host is null.
                    429:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    430:  */
                    431: 
                    432: kern_return_t
                    433: host_virtual_physical_table_info(host, infop, countp)
1.1.1.4   root      434:        const host_t host;
1.1       root      435:        hash_info_bucket_array_t *infop;
                    436:        natural_t *countp;
                    437: {
                    438:        vm_offset_t addr;
                    439:        vm_size_t size = 0;/* '=0' to quiet gcc warnings */
                    440:        hash_info_bucket_t *info;
                    441:        unsigned int potential, actual;
                    442:        kern_return_t kr;
                    443: 
                    444:        if (host == HOST_NULL)
                    445:                return KERN_INVALID_HOST;
                    446: 
                    447:        /* start with in-line data */
                    448: 
                    449:        info = *infop;
                    450:        potential = *countp;
                    451: 
                    452:        for (;;) {
                    453:                actual = vm_page_info(info, potential);
                    454:                if (actual <= potential)
                    455:                        break;
                    456: 
                    457:                /* allocate more memory */
                    458: 
                    459:                if (info != *infop)
                    460:                        kmem_free(ipc_kernel_map, addr, size);
                    461: 
                    462:                size = round_page(actual * sizeof *info);
                    463:                kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size);
                    464:                if (kr != KERN_SUCCESS)
                    465:                        return KERN_RESOURCE_SHORTAGE;
                    466: 
                    467:                info = (hash_info_bucket_t *) addr;
                    468:                potential = size/sizeof *info;
                    469:        }
                    470: 
                    471:        if (info == *infop) {
                    472:                /* data fit in-line; nothing to deallocate */
                    473: 
                    474:                *countp = actual;
                    475:        } else if (actual == 0) {
                    476:                kmem_free(ipc_kernel_map, addr, size);
                    477: 
                    478:                *countp = 0;
                    479:        } else {
                    480:                vm_map_copy_t copy;
                    481:                vm_size_t used;
                    482: 
                    483:                used = round_page(actual * sizeof *info);
                    484: 
                    485:                if (used != size)
                    486:                        kmem_free(ipc_kernel_map, addr + used, size - used);
                    487: 
                    488:                kr = vm_map_copyin(ipc_kernel_map, addr, used,
                    489:                                   TRUE, &copy);
                    490:                assert(kr == KERN_SUCCESS);
                    491: 
                    492:                *infop = (hash_info_bucket_t *) copy;
                    493:                *countp = actual;
                    494:        }
                    495: 
                    496:        return KERN_SUCCESS;
                    497: }

unix.superglobalmegacorp.com

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