|
|
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: 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, ©); 411: assert(kr == KERN_SUCCESS); 412: 413: *pagesp = (vm_page_info_t *) copy; 414: *countp = actual; 415: } 416: 417: return KERN_SUCCESS; 418: } 419: 1.1.1.2 ! root 420: #endif /* MACH_VM_DEBUG */ 1.1 root 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, ©); 492: assert(kr == KERN_SUCCESS); 493: 494: *infop = (hash_info_bucket_t *) copy; 495: *countp = actual; 496: } 497: 498: return KERN_SUCCESS; 499: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.