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