|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: vm/vm_debug.c. ! 54: * Author: Rich Draves ! 55: * Date: March, 1990 ! 56: * ! 57: * Exported kernel calls. See mach_debug/mach_debug.defs. ! 58: */ ! 59: #include <mach_vm_debug.h> ! 60: #include <mach/kern_return.h> ! 61: #include <mach/mach_host_server.h> ! 62: #include <mach/vm_task_server.h> ! 63: #include <mach_debug/vm_info.h> ! 64: #include <mach_debug/page_info.h> ! 65: #include <mach_debug/hash_info.h> ! 66: ! 67: #if MACH_VM_DEBUG ! 68: #include <mach/machine/vm_types.h> ! 69: #include <mach/memory_object_types.h> ! 70: #include <mach/vm_prot.h> ! 71: #include <mach/vm_inherit.h> ! 72: #include <mach/vm_param.h> ! 73: #include <kern/thread.h> ! 74: #include <vm/vm_map.h> ! 75: #include <vm/vm_kern.h> ! 76: #include <vm/vm_object.h> ! 77: #include <kern/task.h> ! 78: #include <kern/host.h> ! 79: #include <ipc/ipc_port.h> ! 80: #include <vm/vm_debug.h> ! 81: #endif ! 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: * KERN_RESOURCE_SHORTAGE Can't allocate memory. ! 95: */ ! 96: ! 97: kern_return_t ! 98: mach_vm_region_info( ! 99: vm_map_t map, ! 100: vm_offset_t address, ! 101: vm_info_region_t *regionp, ! 102: vm_info_object_array_t *objectsp, ! 103: mach_msg_type_number_t *objectsCntp) ! 104: { ! 105: #if !MACH_VM_DEBUG ! 106: return KERN_FAILURE; ! 107: #else ! 108: vm_map_copy_t copy; ! 109: vm_offset_t addr; /* memory for OOL data */ ! 110: vm_size_t size; /* size of the memory */ ! 111: unsigned int room; /* room for this many objects */ ! 112: unsigned int used; /* actually this many objects */ ! 113: vm_info_region_t region; ! 114: kern_return_t kr; ! 115: ! 116: if (map == VM_MAP_NULL) ! 117: return KERN_INVALID_TASK; ! 118: ! 119: size = 0; /* no memory allocated yet */ ! 120: ! 121: for (;;) { ! 122: vm_map_t cmap; /* current map in traversal */ ! 123: vm_map_t nmap; /* next map to look at */ ! 124: vm_map_entry_t entry; ! 125: vm_object_t object, cobject, nobject; ! 126: ! 127: /* nothing is locked */ ! 128: ! 129: vm_map_lock_read(map); ! 130: for (cmap = map;; cmap = nmap) { ! 131: /* cmap is read-locked */ ! 132: ! 133: if (!vm_map_lookup_entry(cmap, address, &entry)) { ! 134: entry = entry->vme_next; ! 135: if (entry == vm_map_to_entry(cmap)) { ! 136: vm_map_unlock_read(cmap); ! 137: if (size != 0) ! 138: kmem_free(ipc_kernel_map, ! 139: addr, size); ! 140: return KERN_NO_SPACE; ! 141: } ! 142: } ! 143: ! 144: if (entry->is_sub_map) ! 145: nmap = entry->object.sub_map; ! 146: else ! 147: break; ! 148: ! 149: /* move down to the lower map */ ! 150: ! 151: vm_map_lock_read(nmap); ! 152: vm_map_unlock_read(cmap); ! 153: } ! 154: ! 155: /* cmap is read-locked; we have a real entry */ ! 156: ! 157: object = entry->object.vm_object; ! 158: region.vir_start = entry->vme_start; ! 159: region.vir_end = entry->vme_end; ! 160: region.vir_object = (vm_offset_t) object; ! 161: region.vir_offset = entry->offset; ! 162: region.vir_needs_copy = entry->needs_copy; ! 163: region.vir_protection = entry->protection; ! 164: region.vir_max_protection = entry->max_protection; ! 165: region.vir_inheritance = entry->inheritance; ! 166: region.vir_wired_count = entry->wired_count; ! 167: region.vir_user_wired_count = entry->user_wired_count; ! 168: ! 169: used = 0; ! 170: room = size / sizeof(vm_info_object_t); ! 171: ! 172: if (object == VM_OBJECT_NULL) { ! 173: vm_map_unlock_read(cmap); ! 174: /* no memory needed */ ! 175: break; ! 176: } ! 177: ! 178: vm_object_lock(object); ! 179: vm_map_unlock_read(cmap); ! 180: ! 181: for (cobject = object;; cobject = nobject) { ! 182: /* cobject is locked */ ! 183: ! 184: if (used < room) { ! 185: vm_info_object_t *vio = ! 186: &((vm_info_object_t *) addr)[used]; ! 187: ! 188: vio->vio_object = ! 189: (vm_offset_t) cobject; ! 190: vio->vio_size = ! 191: cobject->size; ! 192: vio->vio_ref_count = ! 193: cobject->ref_count; ! 194: vio->vio_resident_page_count = ! 195: cobject->resident_page_count; ! 196: vio->vio_absent_count = ! 197: cobject->absent_count; ! 198: vio->vio_copy = ! 199: (vm_offset_t) cobject->copy; ! 200: vio->vio_shadow = ! 201: (vm_offset_t) cobject->shadow; ! 202: vio->vio_shadow_offset = ! 203: cobject->shadow_offset; ! 204: vio->vio_paging_offset = ! 205: cobject->paging_offset; ! 206: vio->vio_copy_strategy = ! 207: cobject->copy_strategy; ! 208: vio->vio_last_alloc = ! 209: cobject->last_alloc; ! 210: vio->vio_paging_in_progress = ! 211: cobject->paging_in_progress; ! 212: vio->vio_pager_created = ! 213: cobject->pager_created; ! 214: vio->vio_pager_initialized = ! 215: cobject->pager_initialized; ! 216: vio->vio_pager_ready = ! 217: cobject->pager_ready; ! 218: vio->vio_can_persist = ! 219: cobject->can_persist; ! 220: vio->vio_internal = ! 221: cobject->internal; ! 222: vio->vio_temporary = ! 223: cobject->temporary; ! 224: vio->vio_alive = ! 225: cobject->alive; ! 226: vio->vio_lock_in_progress = ! 227: cobject->lock_in_progress; ! 228: vio->vio_lock_restart = ! 229: cobject->lock_restart; ! 230: } ! 231: ! 232: used++; ! 233: nobject = cobject->shadow; ! 234: if (nobject == VM_OBJECT_NULL) { ! 235: vm_object_unlock(cobject); ! 236: break; ! 237: } ! 238: ! 239: vm_object_lock(nobject); ! 240: vm_object_unlock(cobject); ! 241: } ! 242: ! 243: /* nothing locked */ ! 244: ! 245: if (used <= room) ! 246: break; ! 247: ! 248: /* must allocate more memory */ ! 249: ! 250: if (size != 0) ! 251: kmem_free(ipc_kernel_map, addr, size); ! 252: size = round_page(2 * used * sizeof(vm_info_object_t)); ! 253: ! 254: kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE); ! 255: if (kr != KERN_SUCCESS) ! 256: return KERN_RESOURCE_SHORTAGE; ! 257: ! 258: kr = vm_map_wire(ipc_kernel_map, addr, addr + size, ! 259: VM_PROT_READ|VM_PROT_WRITE, FALSE); ! 260: assert(kr == KERN_SUCCESS); ! 261: } ! 262: ! 263: /* free excess memory; make remaining memory pageable */ ! 264: ! 265: if (used == 0) { ! 266: copy = VM_MAP_COPY_NULL; ! 267: ! 268: if (size != 0) ! 269: kmem_free(ipc_kernel_map, addr, size); ! 270: } else { ! 271: vm_size_t size_used = ! 272: round_page(used * sizeof(vm_info_object_t)); ! 273: ! 274: kr = vm_map_unwire(ipc_kernel_map, addr, addr + size_used, FALSE); ! 275: assert(kr == KERN_SUCCESS); ! 276: ! 277: kr = vm_map_copyin(ipc_kernel_map, addr, size_used, ! 278: TRUE, ©); ! 279: assert(kr == KERN_SUCCESS); ! 280: ! 281: if (size != size_used) ! 282: kmem_free(ipc_kernel_map, ! 283: addr + size_used, size - size_used); ! 284: } ! 285: ! 286: *regionp = region; ! 287: *objectsp = (vm_info_object_array_t) copy; ! 288: *objectsCntp = used; ! 289: return KERN_SUCCESS; ! 290: #endif /* MACH_VM_DEBUG */ ! 291: } ! 292: ! 293: /* ! 294: * Return an array of virtual pages that are mapped to a task. ! 295: */ ! 296: kern_return_t ! 297: vm_mapped_pages_info( ! 298: vm_map_t map, ! 299: page_address_array_t *pages, ! 300: mach_msg_type_number_t *pages_count) ! 301: { ! 302: #if !MACH_VM_DEBUG ! 303: return KERN_FAILURE; ! 304: #else ! 305: pmap_t pmap; ! 306: vm_size_t size, size_used; ! 307: unsigned int actual, space; ! 308: page_address_array_t list; ! 309: vm_offset_t addr; ! 310: ! 311: if (map == VM_MAP_NULL) ! 312: return (KERN_INVALID_ARGUMENT); ! 313: ! 314: pmap = map->pmap; ! 315: size = pmap_resident_count(pmap) * sizeof(vm_offset_t); ! 316: size = round_page(size); ! 317: ! 318: for (;;) { ! 319: (void) vm_allocate(ipc_kernel_map, &addr, size, TRUE); ! 320: (void) vm_map_unwire(ipc_kernel_map, addr, addr + size, FALSE); ! 321: ! 322: list = (page_address_array_t) addr; ! 323: space = size / sizeof(vm_offset_t); ! 324: ! 325: actual = pmap_list_resident_pages(pmap, ! 326: list, ! 327: space); ! 328: if (actual <= space) ! 329: break; ! 330: ! 331: /* ! 332: * Free memory if not enough ! 333: */ ! 334: (void) kmem_free(ipc_kernel_map, addr, size); ! 335: ! 336: /* ! 337: * Try again, doubling the size ! 338: */ ! 339: size = round_page(actual * sizeof(vm_offset_t)); ! 340: } ! 341: if (actual == 0) { ! 342: *pages = 0; ! 343: *pages_count = 0; ! 344: (void) kmem_free(ipc_kernel_map, addr, size); ! 345: } ! 346: else { ! 347: *pages_count = actual; ! 348: size_used = round_page(actual * sizeof(vm_offset_t)); ! 349: (void) vm_map_wire(ipc_kernel_map, ! 350: addr, addr + size, ! 351: VM_PROT_READ|VM_PROT_WRITE, FALSE); ! 352: (void) vm_map_copyin( ! 353: ipc_kernel_map, ! 354: addr, ! 355: size_used, ! 356: TRUE, ! 357: (vm_map_copy_t *)pages); ! 358: if (size_used != size) { ! 359: (void) kmem_free(ipc_kernel_map, ! 360: addr + size_used, ! 361: size - size_used); ! 362: } ! 363: } ! 364: ! 365: return (KERN_SUCCESS); ! 366: #endif /* MACH_VM_DEBUG */ ! 367: } ! 368: ! 369: /* ! 370: * Routine: host_virtual_physical_table_info ! 371: * Purpose: ! 372: * Return information about the VP table. ! 373: * Conditions: ! 374: * Nothing locked. Obeys CountInOut protocol. ! 375: * Returns: ! 376: * KERN_SUCCESS Returned information. ! 377: * KERN_INVALID_HOST The host is null. ! 378: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 379: */ ! 380: ! 381: kern_return_t ! 382: host_virtual_physical_table_info( ! 383: host_t host, ! 384: hash_info_bucket_array_t *infop, ! 385: mach_msg_type_number_t *countp) ! 386: { ! 387: #if !MACH_VM_DEBUG ! 388: return KERN_FAILURE; ! 389: #else ! 390: vm_offset_t addr; ! 391: vm_size_t size; ! 392: hash_info_bucket_t *info; ! 393: unsigned int potential, actual; ! 394: kern_return_t kr; ! 395: ! 396: if (host == HOST_NULL) ! 397: return KERN_INVALID_HOST; ! 398: ! 399: /* start with in-line data */ ! 400: ! 401: info = *infop; ! 402: potential = *countp; ! 403: ! 404: for (;;) { ! 405: actual = vm_page_info(info, potential); ! 406: if (actual <= potential) ! 407: break; ! 408: ! 409: /* allocate more memory */ ! 410: ! 411: if (info != *infop) ! 412: kmem_free(ipc_kernel_map, addr, size); ! 413: ! 414: size = round_page(actual * sizeof *info); ! 415: kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size); ! 416: if (kr != KERN_SUCCESS) ! 417: return KERN_RESOURCE_SHORTAGE; ! 418: ! 419: info = (hash_info_bucket_t *) addr; ! 420: potential = size/sizeof *info; ! 421: } ! 422: ! 423: if (info == *infop) { ! 424: /* data fit in-line; nothing to deallocate */ ! 425: ! 426: *countp = actual; ! 427: } else if (actual == 0) { ! 428: kmem_free(ipc_kernel_map, addr, size); ! 429: ! 430: *countp = 0; ! 431: } else { ! 432: vm_map_copy_t copy; ! 433: vm_size_t used; ! 434: ! 435: used = round_page(actual * sizeof *info); ! 436: ! 437: if (used != size) ! 438: kmem_free(ipc_kernel_map, addr + used, size - used); ! 439: ! 440: kr = vm_map_copyin(ipc_kernel_map, addr, used, ! 441: TRUE, ©); ! 442: assert(kr == KERN_SUCCESS); ! 443: ! 444: *infop = (hash_info_bucket_t *) copy; ! 445: *countp = actual; ! 446: } ! 447: ! 448: return KERN_SUCCESS; ! 449: #endif /* MACH_VM_DEBUG */ ! 450: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.