|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988 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_user.c
28: * Author: Avadis Tevanian, Jr., Michael Wayne Young
29: *
30: * User-exported virtual memory functions.
31: */
32:
33: #include <mach/boolean.h>
34: #include <mach/kern_return.h>
35: #include <mach/mach_types.h> /* to get vm_address_t */
36: #include <mach/memory_object.h>
37: #include <mach/std_types.h> /* to get pointer_t */
38: #include <mach/vm_attributes.h>
39: #include <mach/vm_param.h>
40: #include <mach/vm_statistics.h>
1.1.1.2 ! root 41: #include <mach/vm_cache_statistics.h>
1.1 root 42: #include <kern/host.h>
43: #include <kern/task.h>
44: #include <vm/vm_fault.h>
1.1.1.2 ! root 45: #include <vm/vm_kern.h>
1.1 root 46: #include <vm/vm_map.h>
47: #include <vm/vm_object.h>
1.1.1.2 ! root 48: #include <vm/memory_object_proxy.h>
1.1 root 49: #include <vm/vm_page.h>
50:
51:
52:
53: vm_statistics_data_t vm_stat;
54:
55: /*
56: * vm_allocate allocates "zero fill" memory in the specfied
57: * map.
58: */
59: kern_return_t vm_allocate(map, addr, size, anywhere)
60: register vm_map_t map;
61: register vm_offset_t *addr;
62: register vm_size_t size;
63: boolean_t anywhere;
64: {
65: kern_return_t result;
66:
67: if (map == VM_MAP_NULL)
68: return(KERN_INVALID_ARGUMENT);
69: if (size == 0) {
70: *addr = 0;
71: return(KERN_SUCCESS);
72: }
73:
74: if (anywhere)
75: *addr = vm_map_min(map);
76: else
77: *addr = trunc_page(*addr);
78: size = round_page(size);
79:
80: result = vm_map_enter(
81: map,
82: addr,
83: size,
84: (vm_offset_t)0,
85: anywhere,
86: VM_OBJECT_NULL,
87: (vm_offset_t)0,
88: FALSE,
89: VM_PROT_DEFAULT,
90: VM_PROT_ALL,
91: VM_INHERIT_DEFAULT);
92:
93: return(result);
94: }
95:
96: /*
97: * vm_deallocate deallocates the specified range of addresses in the
98: * specified address map.
99: */
100: kern_return_t vm_deallocate(map, start, size)
101: register vm_map_t map;
102: vm_offset_t start;
103: vm_size_t size;
104: {
105: if (map == VM_MAP_NULL)
106: return(KERN_INVALID_ARGUMENT);
107:
108: if (size == (vm_offset_t) 0)
109: return(KERN_SUCCESS);
110:
111: return(vm_map_remove(map, trunc_page(start), round_page(start+size)));
112: }
113:
114: /*
115: * vm_inherit sets the inheritance of the specified range in the
116: * specified map.
117: */
118: kern_return_t vm_inherit(map, start, size, new_inheritance)
119: register vm_map_t map;
120: vm_offset_t start;
121: vm_size_t size;
122: vm_inherit_t new_inheritance;
123: {
124: if (map == VM_MAP_NULL)
125: return(KERN_INVALID_ARGUMENT);
126:
127: switch (new_inheritance) {
128: case VM_INHERIT_NONE:
129: case VM_INHERIT_COPY:
130: case VM_INHERIT_SHARE:
131: break;
132: default:
133: return(KERN_INVALID_ARGUMENT);
134: }
135:
136: /*Check if range includes projected buffer;
137: user is not allowed direct manipulation in that case*/
138: if (projected_buffer_in_range(map, start, start+size))
139: return(KERN_INVALID_ARGUMENT);
140:
141: return(vm_map_inherit(map,
142: trunc_page(start),
143: round_page(start+size),
144: new_inheritance));
145: }
146:
147: /*
148: * vm_protect sets the protection of the specified range in the
149: * specified map.
150: */
151:
152: kern_return_t vm_protect(map, start, size, set_maximum, new_protection)
153: register vm_map_t map;
154: vm_offset_t start;
155: vm_size_t size;
156: boolean_t set_maximum;
157: vm_prot_t new_protection;
158: {
159: if ((map == VM_MAP_NULL) ||
160: (new_protection & ~(VM_PROT_ALL|VM_PROT_NOTIFY)))
161: return(KERN_INVALID_ARGUMENT);
162:
163: /*Check if range includes projected buffer;
164: user is not allowed direct manipulation in that case*/
165: if (projected_buffer_in_range(map, start, start+size))
166: return(KERN_INVALID_ARGUMENT);
167:
168: return(vm_map_protect(map,
169: trunc_page(start),
170: round_page(start+size),
171: new_protection,
172: set_maximum));
173: }
174:
175: kern_return_t vm_statistics(map, stat)
176: vm_map_t map;
177: vm_statistics_data_t *stat;
178: {
179: if (map == VM_MAP_NULL)
180: return(KERN_INVALID_ARGUMENT);
181:
182: *stat = vm_stat;
183:
184: stat->pagesize = PAGE_SIZE;
185: stat->free_count = vm_page_free_count;
186: stat->active_count = vm_page_active_count;
187: stat->inactive_count = vm_page_inactive_count;
188: stat->wire_count = vm_page_wire_count;
189:
190: return(KERN_SUCCESS);
191: }
192:
1.1.1.2 ! root 193: kern_return_t vm_cache_statistics(
! 194: vm_map_t map,
! 195: vm_cache_statistics_data_t *stats)
! 196: {
! 197: if (map == VM_MAP_NULL)
! 198: return KERN_INVALID_ARGUMENT;
! 199:
! 200: stats->cache_object_count = vm_object_cached_count;
! 201: stats->cache_count = vm_object_cached_pages;
! 202:
! 203: /* XXX Not implemented yet */
! 204: stats->active_tmp_count = 0;
! 205: stats->inactive_tmp_count = 0;
! 206: stats->active_perm_count = 0;
! 207: stats->inactive_perm_count = 0;
! 208: stats->dirty_count = 0;
! 209: stats->laundry_count = 0;
! 210: stats->writeback_count = 0;
! 211: stats->slab_count = 0;
! 212: stats->slab_reclaim_count = 0;
! 213: return KERN_SUCCESS;
! 214: }
! 215:
1.1 root 216: /*
217: * Handle machine-specific attributes for a mapping, such
218: * as cachability, migrability, etc.
219: */
220: kern_return_t vm_machine_attribute(map, address, size, attribute, value)
221: vm_map_t map;
222: vm_address_t address;
223: vm_size_t size;
224: vm_machine_attribute_t attribute;
225: vm_machine_attribute_val_t* value; /* IN/OUT */
226: {
227: extern kern_return_t vm_map_machine_attribute();
228:
229: if (map == VM_MAP_NULL)
230: return(KERN_INVALID_ARGUMENT);
231:
232: /*Check if range includes projected buffer;
233: user is not allowed direct manipulation in that case*/
234: if (projected_buffer_in_range(map, address, address+size))
235: return(KERN_INVALID_ARGUMENT);
236:
237: return vm_map_machine_attribute(map, address, size, attribute, value);
238: }
239:
240: kern_return_t vm_read(map, address, size, data, data_size)
241: vm_map_t map;
242: vm_address_t address;
243: vm_size_t size;
244: pointer_t *data;
245: vm_size_t *data_size;
246: {
247: kern_return_t error;
248: vm_map_copy_t ipc_address;
249:
250: if (map == VM_MAP_NULL)
251: return(KERN_INVALID_ARGUMENT);
252:
253: if ((error = vm_map_copyin(map,
254: address,
255: size,
256: FALSE, /* src_destroy */
257: &ipc_address)) == KERN_SUCCESS) {
258: *data = (pointer_t) ipc_address;
259: *data_size = size;
260: }
261: return(error);
262: }
263:
264: kern_return_t vm_write(map, address, data, size)
265: vm_map_t map;
266: vm_address_t address;
267: pointer_t data;
268: vm_size_t size;
269: {
270: if (map == VM_MAP_NULL)
271: return KERN_INVALID_ARGUMENT;
272:
273: return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data,
274: FALSE /* interruptible XXX */);
275: }
276:
277: kern_return_t vm_copy(map, source_address, size, dest_address)
278: vm_map_t map;
279: vm_address_t source_address;
280: vm_size_t size;
281: vm_address_t dest_address;
282: {
283: vm_map_copy_t copy;
284: kern_return_t kr;
285:
286: if (map == VM_MAP_NULL)
287: return KERN_INVALID_ARGUMENT;
288:
289: kr = vm_map_copyin(map, source_address, size,
290: FALSE, ©);
291: if (kr != KERN_SUCCESS)
292: return kr;
293:
294: kr = vm_map_copy_overwrite(map, dest_address, copy,
295: FALSE /* interruptible XXX */);
296: if (kr != KERN_SUCCESS) {
297: vm_map_copy_discard(copy);
298: return kr;
299: }
300:
301: return KERN_SUCCESS;
302: }
303:
1.1.1.2 ! root 304:
1.1 root 305: /*
306: * Routine: vm_map
307: */
308: kern_return_t vm_map(
309: target_map,
310: address, size, mask, anywhere,
311: memory_object, offset,
312: copy,
313: cur_protection, max_protection, inheritance)
314: vm_map_t target_map;
315: vm_offset_t *address;
316: vm_size_t size;
317: vm_offset_t mask;
318: boolean_t anywhere;
319: ipc_port_t memory_object;
320: vm_offset_t offset;
321: boolean_t copy;
322: vm_prot_t cur_protection;
323: vm_prot_t max_protection;
324: vm_inherit_t inheritance;
325: {
326: register
327: vm_object_t object;
328: register
329: kern_return_t result;
330:
331: if ((target_map == VM_MAP_NULL) ||
332: (cur_protection & ~VM_PROT_ALL) ||
333: (max_protection & ~VM_PROT_ALL))
334: return(KERN_INVALID_ARGUMENT);
335:
336: switch (inheritance) {
337: case VM_INHERIT_NONE:
338: case VM_INHERIT_COPY:
339: case VM_INHERIT_SHARE:
340: break;
341: default:
342: return(KERN_INVALID_ARGUMENT);
343: }
344:
1.1.1.2 ! root 345: if (size == 0)
! 346: return KERN_INVALID_ARGUMENT;
! 347:
1.1 root 348: *address = trunc_page(*address);
349: size = round_page(size);
350:
351: if (!IP_VALID(memory_object)) {
352: object = VM_OBJECT_NULL;
353: offset = 0;
354: copy = FALSE;
355: } else if ((object = vm_object_enter(memory_object, size, FALSE))
356: == VM_OBJECT_NULL)
1.1.1.2 ! root 357: {
! 358: ipc_port_t real_memobj;
! 359: vm_prot_t prot;
! 360: result = memory_object_proxy_lookup (memory_object, &real_memobj,
! 361: &prot);
! 362: if (result != KERN_SUCCESS)
! 363: return result;
! 364:
! 365: /* Reduce the allowed access to the memory object. */
! 366: max_protection &= prot;
! 367: cur_protection &= prot;
! 368:
! 369: if ((object = vm_object_enter(real_memobj, size, FALSE))
! 370: == VM_OBJECT_NULL)
! 371: return KERN_INVALID_ARGUMENT;
! 372: }
1.1 root 373:
374: /*
375: * Perform the copy if requested
376: */
377:
378: if (copy) {
379: vm_object_t new_object;
380: vm_offset_t new_offset;
381:
382: result = vm_object_copy_strategically(object, offset, size,
383: &new_object, &new_offset,
384: ©);
385:
386: /*
387: * Throw away the reference to the
388: * original object, as it won't be mapped.
389: */
390:
391: vm_object_deallocate(object);
392:
393: if (result != KERN_SUCCESS)
394: return (result);
395:
396: object = new_object;
397: offset = new_offset;
398: }
399:
400: if ((result = vm_map_enter(target_map,
401: address, size, mask, anywhere,
402: object, offset,
403: copy,
404: cur_protection, max_protection, inheritance
405: )) != KERN_SUCCESS)
406: vm_object_deallocate(object);
407: return(result);
408: }
409:
410: /*
411: * Specify that the range of the virtual address space
412: * of the target task must not cause page faults for
413: * the indicated accesses.
414: *
415: * [ To unwire the pages, specify VM_PROT_NONE. ]
416: */
417: kern_return_t vm_wire(host, map, start, size, access)
418: host_t host;
419: register vm_map_t map;
420: vm_offset_t start;
421: vm_size_t size;
422: vm_prot_t access;
423: {
424: if (host == HOST_NULL)
425: return KERN_INVALID_HOST;
426:
427: if (map == VM_MAP_NULL)
428: return KERN_INVALID_TASK;
429:
430: if (access & ~VM_PROT_ALL)
431: return KERN_INVALID_ARGUMENT;
432:
433: /*Check if range includes projected buffer;
434: user is not allowed direct manipulation in that case*/
435: if (projected_buffer_in_range(map, start, start+size))
436: return(KERN_INVALID_ARGUMENT);
437:
438: return vm_map_pageable_user(map,
439: trunc_page(start),
440: round_page(start+size),
441: access);
442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.