|
|
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: */
1.1.1.3 ! root 59: kern_return_t vm_allocate(
! 60: vm_map_t map,
! 61: vm_offset_t *addr,
! 62: vm_size_t size,
! 63: boolean_t anywhere)
1.1 root 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: */
1.1.1.3 ! root 100: kern_return_t vm_deallocate(
! 101: vm_map_t map,
! 102: vm_offset_t start,
! 103: vm_size_t size)
1.1 root 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: */
1.1.1.3 ! root 118: kern_return_t vm_inherit(
! 119: vm_map_t map,
! 120: vm_offset_t start,
! 121: vm_size_t size,
! 122: vm_inherit_t new_inheritance)
1.1 root 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:
1.1.1.3 ! root 152: kern_return_t vm_protect(
! 153: 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)
1.1 root 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:
1.1.1.3 ! root 175: kern_return_t vm_statistics(
! 176: vm_map_t map,
! 177: vm_statistics_data_t *stat)
1.1 root 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: */
1.1.1.3 ! root 220: kern_return_t vm_machine_attribute(
! 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 */
1.1 root 226: {
227: if (map == VM_MAP_NULL)
228: return(KERN_INVALID_ARGUMENT);
229:
230: /*Check if range includes projected buffer;
231: user is not allowed direct manipulation in that case*/
232: if (projected_buffer_in_range(map, address, address+size))
233: return(KERN_INVALID_ARGUMENT);
234:
235: return vm_map_machine_attribute(map, address, size, attribute, value);
236: }
237:
1.1.1.3 ! root 238: kern_return_t vm_read(
! 239: vm_map_t map,
! 240: vm_address_t address,
! 241: vm_size_t size,
! 242: pointer_t *data,
! 243: vm_size_t *data_size)
1.1 root 244: {
245: kern_return_t error;
246: vm_map_copy_t ipc_address;
247:
248: if (map == VM_MAP_NULL)
249: return(KERN_INVALID_ARGUMENT);
250:
251: if ((error = vm_map_copyin(map,
252: address,
253: size,
254: FALSE, /* src_destroy */
255: &ipc_address)) == KERN_SUCCESS) {
256: *data = (pointer_t) ipc_address;
257: *data_size = size;
258: }
259: return(error);
260: }
261:
1.1.1.3 ! root 262: kern_return_t vm_write(
! 263: vm_map_t map,
! 264: vm_address_t address,
! 265: pointer_t data,
! 266: vm_size_t size)
1.1 root 267: {
268: if (map == VM_MAP_NULL)
269: return KERN_INVALID_ARGUMENT;
270:
271: return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data,
272: FALSE /* interruptible XXX */);
273: }
274:
1.1.1.3 ! root 275: kern_return_t vm_copy(
! 276: vm_map_t map,
! 277: vm_address_t source_address,
! 278: vm_size_t size,
! 279: vm_address_t dest_address)
1.1 root 280: {
281: vm_map_copy_t copy;
282: kern_return_t kr;
283:
284: if (map == VM_MAP_NULL)
285: return KERN_INVALID_ARGUMENT;
286:
287: kr = vm_map_copyin(map, source_address, size,
288: FALSE, ©);
289: if (kr != KERN_SUCCESS)
290: return kr;
291:
292: kr = vm_map_copy_overwrite(map, dest_address, copy,
293: FALSE /* interruptible XXX */);
294: if (kr != KERN_SUCCESS) {
295: vm_map_copy_discard(copy);
296: return kr;
297: }
298:
299: return KERN_SUCCESS;
300: }
301:
1.1.1.2 root 302:
1.1 root 303: /*
304: * Routine: vm_map
305: */
306: kern_return_t vm_map(
1.1.1.3 ! root 307: vm_map_t target_map,
! 308: vm_offset_t *address,
! 309: vm_size_t size,
! 310: vm_offset_t mask,
! 311: boolean_t anywhere,
! 312: ipc_port_t memory_object,
! 313: vm_offset_t offset,
! 314: boolean_t copy,
! 315: vm_prot_t cur_protection,
! 316: vm_prot_t max_protection,
! 317: vm_inherit_t inheritance)
1.1 root 318: {
319: vm_object_t object;
320: kern_return_t result;
321:
322: if ((target_map == VM_MAP_NULL) ||
323: (cur_protection & ~VM_PROT_ALL) ||
324: (max_protection & ~VM_PROT_ALL))
325: return(KERN_INVALID_ARGUMENT);
326:
327: switch (inheritance) {
328: case VM_INHERIT_NONE:
329: case VM_INHERIT_COPY:
330: case VM_INHERIT_SHARE:
331: break;
332: default:
333: return(KERN_INVALID_ARGUMENT);
334: }
335:
1.1.1.2 root 336: if (size == 0)
337: return KERN_INVALID_ARGUMENT;
338:
1.1 root 339: *address = trunc_page(*address);
340: size = round_page(size);
341:
342: if (!IP_VALID(memory_object)) {
343: object = VM_OBJECT_NULL;
344: offset = 0;
345: copy = FALSE;
346: } else if ((object = vm_object_enter(memory_object, size, FALSE))
347: == VM_OBJECT_NULL)
1.1.1.2 root 348: {
349: ipc_port_t real_memobj;
350: vm_prot_t prot;
351: result = memory_object_proxy_lookup (memory_object, &real_memobj,
352: &prot);
353: if (result != KERN_SUCCESS)
354: return result;
355:
356: /* Reduce the allowed access to the memory object. */
357: max_protection &= prot;
358: cur_protection &= prot;
359:
360: if ((object = vm_object_enter(real_memobj, size, FALSE))
361: == VM_OBJECT_NULL)
362: return KERN_INVALID_ARGUMENT;
363: }
1.1 root 364:
365: /*
366: * Perform the copy if requested
367: */
368:
369: if (copy) {
370: vm_object_t new_object;
371: vm_offset_t new_offset;
372:
373: result = vm_object_copy_strategically(object, offset, size,
374: &new_object, &new_offset,
375: ©);
376:
377: /*
378: * Throw away the reference to the
379: * original object, as it won't be mapped.
380: */
381:
382: vm_object_deallocate(object);
383:
384: if (result != KERN_SUCCESS)
385: return (result);
386:
387: object = new_object;
388: offset = new_offset;
389: }
390:
391: if ((result = vm_map_enter(target_map,
392: address, size, mask, anywhere,
393: object, offset,
394: copy,
395: cur_protection, max_protection, inheritance
396: )) != KERN_SUCCESS)
397: vm_object_deallocate(object);
398: return(result);
399: }
400:
401: /*
402: * Specify that the range of the virtual address space
403: * of the target task must not cause page faults for
404: * the indicated accesses.
405: *
406: * [ To unwire the pages, specify VM_PROT_NONE. ]
407: */
408: kern_return_t vm_wire(host, map, start, size, access)
1.1.1.3 ! root 409: const host_t host;
! 410: vm_map_t map;
1.1 root 411: vm_offset_t start;
412: vm_size_t size;
413: vm_prot_t access;
414: {
415: if (host == HOST_NULL)
416: return KERN_INVALID_HOST;
417:
418: if (map == VM_MAP_NULL)
419: return KERN_INVALID_TASK;
420:
421: if (access & ~VM_PROT_ALL)
422: return KERN_INVALID_ARGUMENT;
423:
424: /*Check if range includes projected buffer;
425: user is not allowed direct manipulation in that case*/
426: if (projected_buffer_in_range(map, start, start+size))
427: return(KERN_INVALID_ARGUMENT);
428:
429: return vm_map_pageable_user(map,
430: trunc_page(start),
431: round_page(start+size),
432: access);
433: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.