|
|
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.