xref: /NextBSD/sys/compat/mach/mach_vm.c (revision 6283aa8b8e910d10094766cf10d892a509825cc1)
1 /*-
2  * Copyright (c) 2014-2015, Matthew Macy <mmacy@nextbsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *
11  *  2. Neither the name of Matthew Macy nor the names of its
12  *     contributors may be used to endorse or promote products derived from
13  *     this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/mount.h>
36 #include <sys/proc.h>
37 #include <sys/mman.h>
38 #include <sys/malloc.h>
39 #include <sys/file.h>
40 #include <sys/filedesc.h>
41 #include <sys/exec.h>
42 #include <sys/sysproto.h>
43 #include <sys/uio.h>
44 #include <sys/vnode.h>
45 
46 #include <sys/ktrace.h>
47 
48 #include <vm/vm.h>
49 #include <vm/vm_param.h>
50 #include <vm/pmap.h>
51 #include <vm/vm_map.h>
52 #include <vm/vm_extern.h>
53 #include <vm/vm_kern.h>
54 
55 #include <sys/mach/mach_types.h>
56 #include <sys/mach/mach_vm.h>
57 #include <sys/mach/ipc/ipc_kmsg.h>
58 #include <sys/mach/thread.h>
59 #include <sys/mach/mach_vm_server.h>
60 #include <sys/mach/vm_map_server.h>
61 #include <sys/mach/host_priv_server.h>
62 
63 
64 extern vm_size_t	msg_ool_size_small;
65 void _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end);
66 void _vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start);
67 
68 
69 /*
70  *	vm_map_clip_start:	[ internal use only ]
71  *
72  *	Asserts that the given entry begins at or after
73  *	the specified address; if necessary,
74  *	it splits the entry into two.
75  */
76 #define vm_map_clip_start(map, entry, startaddr) \
77 { \
78 	if (startaddr > entry->start) \
79 		_vm_map_clip_start(map, entry, startaddr); \
80 }
81 
82 /*
83  *	vm_map_clip_end:	[ internal use only ]
84  *
85  *	Asserts that the given entry ends at or before
86  *	the specified address; if necessary,
87  *	it splits the entry into two.
88  */
89 #define vm_map_clip_end(map, entry, endaddr) \
90 { \
91 	if ((endaddr) < (entry->end)) \
92 		_vm_map_clip_end((map), (entry), (endaddr)); \
93 }
94 
95 
96 int mach_vm_map_page_query(vm_map_t target_map, vm_offset_t offset, integer_t *disposition, integer_t *ref_count);
97 int mach_vm_mapped_pages_info(vm_map_t task, page_address_array_t *pages, mach_msg_type_number_t *pagesCnt);
98 int mach_vm_wire_32(
99 	host_priv_t host_priv,
100 	vm_map_t task,
101 	vm_address_t address,
102 	vm_size_t size,
103 	vm_prot_t desired_access
104 	);
105 
106 
107 static kern_return_t
108 vm_map_copyout_internal(
109 	register vm_map_t	dst_map,
110 	vm_offset_t		*dst_addr,	/* OUT */
111 	register vm_map_copy_t	copy,
112 	boolean_t consume_on_success,
113 	vm_prot_t cur_protection,
114 	vm_prot_t max_protection,
115 	vm_inherit_t inheritance);
116 
117 
118 #ifdef INVARIANTS
119 static int
first_free_is_valid(vm_map_t map)120 first_free_is_valid(vm_map_t map)
121 {
122 	return TRUE;
123 }
124 #endif
125 
126 int
mach_vm_map(vm_map_t map,mach_vm_address_t * address,mach_vm_size_t _size,mach_vm_offset_t _mask,int _flags,mem_entry_name_port_t object __unused,memory_object_offset_t offset __unused,boolean_t copy __unused,vm_prot_t cur_protection,vm_prot_t max_protection,vm_inherit_t inh)127 mach_vm_map(vm_map_t map, mach_vm_address_t *address, mach_vm_size_t _size,
128 			mach_vm_offset_t _mask, int _flags, mem_entry_name_port_t object __unused,
129 			memory_object_offset_t offset __unused, boolean_t copy __unused,
130 			vm_prot_t cur_protection, vm_prot_t max_protection, vm_inherit_t inh)
131 {
132 	vm_offset_t addr = 0;
133 	size_t size;
134 	int flags;
135 	int docow, error, find_space;
136 
137 	/* XXX Darwin fails on mapping a page at address 0 */
138 	if ((_flags & VM_FLAGS_ANYWHERE) == 0 && *address == 0)
139 		return (ENOMEM);
140 
141 	size = round_page(_size);
142 	docow = error = 0;
143 
144 	if (!(_mask & (_mask + 1)) && _mask != 0)
145 		_mask++;
146 
147 	find_space = _mask ? VMFS_ALIGNED_SPACE(ffs(_mask)) : VMFS_ANY_SPACE;
148 	flags = MAP_ANON;
149 	if ((_flags & VM_FLAGS_ANYWHERE) == 0) {
150 		flags |= MAP_FIXED;
151 		addr = trunc_page(*address);
152 	} else
153 		addr = 0;
154 
155 	switch(inh) {
156 	case VM_INHERIT_SHARE:
157 		flags |= MAP_INHERIT_SHARE;
158 		break;
159 	case VM_INHERIT_COPY:
160 		flags |= MAP_COPY_ON_WRITE;
161 		docow = MAP_COPY_ON_WRITE;
162 		break;
163 	case VM_INHERIT_NONE:
164 		break;
165 	case VM_INHERIT_DONATE_COPY:
166 	default:
167 		uprintf("mach_vm_map: unsupported inheritance flag %d\n", inh);
168 		break;
169 	}
170 
171 	if (vm_map_find(map, NULL, 0, &addr, size, 0, find_space,
172 	    cur_protection, max_protection, docow) != KERN_SUCCESS) {
173 		error = ENOMEM;
174 		goto done;
175 	}
176 
177 	*address = addr;
178 done:
179 	return (error);
180 }
181 
182 int
vm_allocate(vm_map_t map,vm_offset_t * addr,size_t _size,int flags)183 vm_allocate(vm_map_t map, vm_offset_t *addr, size_t _size, int flags)
184 {
185 
186 	return (mach_vm_allocate(map, addr, _size, flags));
187 }
188 
189 int
mach_vm_allocate(vm_map_t map,vm_offset_t * addr,size_t _size,int flags)190 mach_vm_allocate(vm_map_t map, vm_offset_t *addr, size_t _size, int flags)
191 {
192 	size_t size = round_page(_size);
193 	vm_offset_t start, daddr;
194 	vm_prot_t prot, protmax;
195 	int err;
196 
197 	prot = VM_PROT_READ|VM_PROT_WRITE;
198 	protmax = VM_PROT_ALL;
199 	KASSERT(addr != NULL, ("invalid addr passed"));
200 #if defined(INVARIANTS) && defined(__LP64__)
201 	start = 1UL<<32;
202 #else
203 	start = 0;
204 #endif
205 
206 	daddr = trunc_page(*addr);
207 	vm_map_lock(map);
208 	if ((flags & VM_FLAGS_ANYWHERE) &&
209 		(vm_map_findspace(map, 0, size, &daddr))) {
210 	  err = ENOMEM;
211 	  goto error;
212 	} else {
213 	  err = EINVAL;
214 		/* Address range must be all in user VM space. */
215 		if (daddr < vm_map_min(map) ||
216 		    daddr + size > vm_map_max(map))
217 		  goto error;
218 		if (daddr + size < daddr)
219 		  goto error;
220 	}
221 	if (vm_map_insert(map, NULL, 0, daddr, daddr + size, prot, protmax, 0)) {
222 	  err = EFAULT;
223 	  goto error;
224 	}
225 	vm_map_unlock(map);
226 	*addr = daddr;
227 	return (0);
228  error:
229 	vm_map_unlock(map);
230 	return (err);
231 }
232 
233 int
vm_deallocate(vm_map_t map,vm_offset_t addr,size_t len)234 vm_deallocate(vm_map_t map, vm_offset_t addr, size_t len)
235 {
236 
237 	return (mach_vm_deallocate(map, addr, len));
238 }
239 
240 int
mach_vm_deallocate(vm_map_t target __unused,mach_vm_address_t addr,mach_vm_size_t len)241 mach_vm_deallocate(vm_map_t target __unused, mach_vm_address_t addr, mach_vm_size_t len)
242 {
243 	struct munmap_args cup;
244 
245 	cup.addr = (void *)addr;
246 	cup.len = len;
247 	return (sys_munmap(curthread, &cup));
248 }
249 
250 int
mach_vm_protect(vm_map_t target_task __unused,vm_offset_t addr,size_t len,boolean_t setmax __unused,vm_prot_t prot)251 mach_vm_protect(vm_map_t target_task __unused, vm_offset_t addr, size_t len,
252 				boolean_t setmax __unused, vm_prot_t prot)
253 {
254 	struct mprotect_args cup;
255 
256 	cup.addr = (void *)addr;
257 	cup.len = len;
258 	cup.prot = prot;
259 
260 	return (sys_mprotect(curthread, &cup));
261 }
262 
263 
264 int
mach_vm_inherit(vm_map_t target_task,mach_vm_address_t address,mach_vm_size_t size,vm_inherit_t new_inheritance)265 mach_vm_inherit(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size,
266 				vm_inherit_t new_inheritance)
267 {
268 	struct minherit_args cup;
269 	int error;
270 
271 	cup.addr = (void *)address;
272 	cup.len = size;
273 	cup.inherit = new_inheritance;
274 
275 	if ((error = sys_minherit(curthread, &cup)) != 0)
276 		return (KERN_FAILURE);
277 
278 	return (0);
279 }
280 
281 int
mach_vm_map_page_query(vm_map_t target_map,vm_offset_t offset,integer_t * disposition,integer_t * ref_count)282 mach_vm_map_page_query(
283 	vm_map_t target_map,
284 	vm_offset_t offset,
285 	integer_t *disposition,
286 	integer_t *ref_count
287 )
288 {
289 	return (KERN_NOT_SUPPORTED);
290 }
291 
292 int
_mach_make_memory_entry(vm_map_t target_task,memory_object_size_t * size,memory_object_offset_t offset,vm_prot_t permission,mem_entry_name_port_t * object_handle,mem_entry_name_port_t parent_handle)293 _mach_make_memory_entry(
294 	vm_map_t target_task,
295 	memory_object_size_t *size,
296 	memory_object_offset_t offset,
297 	vm_prot_t permission,
298 	mem_entry_name_port_t *object_handle,
299 	mem_entry_name_port_t parent_handle
300 )
301 {
302 
303 	return (KERN_NOT_SUPPORTED);
304 }
305 
306 int
mach_make_memory_entry(vm_map_t target_task,vm_size_t * size,vm_offset_t offset,vm_prot_t permission,mem_entry_name_port_t * object_handle,mem_entry_name_port_t parent_handle)307 mach_make_memory_entry(vm_map_t target_task, vm_size_t *size,
308 					   vm_offset_t offset, vm_prot_t permission,
309 					   mem_entry_name_port_t *object_handle,
310 					   mem_entry_name_port_t parent_handle)
311 {
312 
313 	return (KERN_NOT_SUPPORTED);
314 }
315 
316 
317 int
mach_make_memory_entry_64(vm_map_t target_task,memory_object_size_t * size,memory_object_offset_t offset,vm_prot_t permission,mach_port_t * object_handle,mem_entry_name_port_t parent_handle)318 mach_make_memory_entry_64(vm_map_t target_task, memory_object_size_t *size,
319 						  memory_object_offset_t offset, vm_prot_t permission,
320 						  mach_port_t *object_handle,
321 						  mem_entry_name_port_t parent_handle)
322 {
323 
324 	return (KERN_NOT_SUPPORTED);
325 }
326 
327 
328 int
mach_vm_msync(vm_map_t target_task __unused,mach_vm_address_t addr,mach_vm_size_t size,vm_sync_t flags)329 mach_vm_msync(vm_map_t target_task __unused, mach_vm_address_t addr, mach_vm_size_t size,
330 		vm_sync_t flags)
331 {
332 	struct msync_args cup;
333 	int error;
334 
335 	cup.addr = (void *)addr;
336 	cup.len = size;
337 	cup.flags = 0;
338 	if (flags & VM_SYNC_ASYNCHRONOUS)
339 		cup.flags |= MS_ASYNC;
340 	if (flags & VM_SYNC_SYNCHRONOUS)
341 		cup.flags |= MS_SYNC;
342 	if (flags & VM_SYNC_INVALIDATE)
343 		cup.flags |= MS_INVALIDATE;
344 	error = sys_msync(curthread, &cup);
345 
346 	if (error)
347 		return (KERN_FAILURE);
348 	return (0);
349 }
350 
351 /* XXX Do it for remote task */
352 int
mach_vm_copy(vm_map_t target_task,mach_vm_address_t src,mach_vm_size_t size,mach_vm_address_t dst)353 mach_vm_copy(vm_map_t target_task, mach_vm_address_t src, mach_vm_size_t size,
354 		mach_vm_address_t dst)
355 
356 {
357 	char *tmpbuf;
358 	int error;
359 
360 #ifdef DEBUG_MACH_VM
361 	printf("mach_vm_copy: src = 0x%08lx, size = 0x%08lx, addr = 0x%08lx\n",
362 	    (long)req->req_src, (long)req->req_size, (long)req->req_addr);
363 #endif
364 	if ((src & (PAGE_SIZE - 1)) ||
365 	    (dst & (PAGE_SIZE - 1)) ||
366 	    (size & (PAGE_SIZE - 1)))
367 		return (KERN_INVALID_ARGUMENT);
368 
369 
370 	tmpbuf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
371 
372 	/* Is there an easy way of dealing with that efficiently? */
373 	do {
374 		if ((error = copyin((void*)src, tmpbuf, PAGE_SIZE)) != 0)
375 			goto out;
376 
377 		if ((error = copyout(tmpbuf, (void *)dst, PAGE_SIZE)) != 0)
378 			goto out;
379 
380 		src += PAGE_SIZE;
381 		dst += PAGE_SIZE;
382 		size -= PAGE_SIZE;
383 	} while (size > 0);
384 
385 	free(tmpbuf, M_TEMP);
386 	return (0);
387 
388 out:
389 	free(tmpbuf, M_TEMP);
390 	return (KERN_FAILURE);
391 }
392 
393 int
mach_vm_read(vm_map_t map,mach_vm_address_t addr,mach_vm_size_t size,vm_offset_t * data,mach_msg_type_number_t * dataCnt)394 mach_vm_read(vm_map_t map, mach_vm_address_t addr, mach_vm_size_t size,
395 			 vm_offset_t *data, mach_msg_type_number_t *dataCnt)
396 {
397 	caddr_t tbuf;
398 	vm_offset_t dstaddr;
399 	vm_prot_t prot, protmax;
400 	int error;
401 
402 	size = round_page(size);
403 	prot = VM_PROT_READ|VM_PROT_WRITE;
404 	protmax = VM_PROT_ALL;
405 
406 	if ((error = mach_vm_allocate(map, &dstaddr, size, 0)))
407 		return (KERN_NO_SPACE);
408 	/*
409 	 * Copy the data from the target process to the current process
410 	 * This is reasonable for small chunk of data, but we should
411 	 * remap COW for areas bigger than a page.
412 	 */
413 	tbuf = malloc(size, M_MACH_TMP, M_WAITOK);
414 #ifdef notyet
415 	if ((error = copyin_vm_map(map, (caddr_t)addr, tbuf, size)) != 0) {
416 		printf("copyin_proc error = %d, addr = %lx, size = %zx\n", error, addr, size);
417 		free(tbuf, M_MACH_TMP);
418 		return (KERN_PROTECTION_FAILURE);
419 	}
420 #endif
421 	if ((error = copyout(tbuf, (void *)dstaddr, size)) != 0) {
422 		printf("copyout error = %d\n", error);
423 		free(tbuf, M_MACH_TMP);
424 		return (KERN_PROTECTION_FAILURE);
425 	}
426 
427 	free(tbuf, M_MACH_TMP);
428 	return (0);
429 }
430 
431 
432 /*
433  * mach_vm_write -
434  * Overwrite the specified address range with the data provided
435  * (from the current map).
436  */
437 kern_return_t
mach_vm_write(vm_map_t map,mach_vm_address_t address,vm_offset_t data,mach_msg_type_number_t size __unused)438 mach_vm_write(
439 	vm_map_t			map,
440 	mach_vm_address_t		address,
441 	vm_offset_t			data,
442 	mach_msg_type_number_t	size __unused)
443 {
444 	if (map == VM_MAP_NULL)
445 		return KERN_INVALID_ARGUMENT;
446 
447 	return vm_map_copy_overwrite(map, (vm_map_address_t)address,
448 		(vm_map_copy_t) data, FALSE /* interruptible XXX */);
449 }
450 
451 int
mach_vm_machine_attribute(vm_map_t target_task,mach_vm_address_t addr,mach_vm_size_t size,vm_machine_attribute_t attribute,vm_machine_attribute_val_t * valuep)452 mach_vm_machine_attribute(vm_map_t target_task, mach_vm_address_t addr, mach_vm_size_t size,
453 						  vm_machine_attribute_t attribute, vm_machine_attribute_val_t *valuep)
454 {
455 	int error = 0;
456 	vm_machine_attribute_val_t value;
457 
458 
459 	if ((error = copyin(valuep, &value, sizeof(value))))
460 		return (KERN_PROTECTION_FAILURE);
461 
462 	switch (attribute) {
463 	case MATTR_CACHE:
464 		switch(value) {
465 		case MATTR_VAL_CACHE_FLUSH:
466 		case MATTR_VAL_DCACHE_FLUSH:
467 		case MATTR_VAL_ICACHE_FLUSH:
468 		case MATTR_VAL_CACHE_SYNC:
469 #ifdef notyet
470 			error = cpu_mach_vm_machine_attribute(target_task, addr, size, &value);
471 #endif
472 			break;
473 		default:
474 #ifdef DEBUG_MACH
475 			printf("unimplemented value %d\n", value);
476 #endif
477 			error = EINVAL;
478 			break;
479 		}
480 		break;
481 
482 	case MATTR_MIGRATE:
483 	case MATTR_REPLICATE:
484 	default:
485 #ifdef DEBUG_MACH
486 		printf("unimplemented attribute %d\n", attribute);
487 #endif
488 		error = EINVAL;
489 		break;
490 	}
491 
492 
493 	if (error)
494 		return (KERN_FAILURE);
495 
496 	return (copyout(&value, valuep, sizeof(value)));
497 }
498 
499 /*
500  *	vm_map_entry_dispose:	[ internal use only ]
501  *
502  *	Inverse of vm_map_entry_create.
503  */
504 #define	vm_map_entry_dispose(map, entry)		\
505 MACRO_BEGIN						\
506 	assert((entry) != (map)->first_free &&		\
507 	       (entry) != (map)->hint);			\
508 	_vm_map_entry_dispose(&(map)->hdr, (entry));	\
509 MACRO_END
510 
511 #define	vm_map_copy_entry_dispose(map, entry) \
512 	_vm_map_entry_dispose(&(copy)->cpy_hdr, (entry))
513 
514 static uma_zone_t vm_map_entry_zone;
515 static uma_zone_t vm_map_kentry_zone;
516 
517 static void
_vm_map_entry_dispose(register struct vm_map_header * map_header,register vm_map_entry_t entry)518 _vm_map_entry_dispose(
519 	register struct vm_map_header	*map_header,
520 	register vm_map_entry_t		entry)
521 {
522 	uma_zone_t		zone;
523 
524 	if (map_header->entries_pageable)
525 	    zone = vm_map_entry_zone;
526 	else
527 	    zone = vm_map_kentry_zone;
528 
529 	uma_zfree(zone, entry);
530 }
531 
532 /*
533  *	Routine: vm_map_copyin_internal [internal use only]
534  *
535  *	Description:
536  *		Copy in data to a kernel buffer from space in the
537  *		source map. The original space may be optionally
538  *		deallocated.
539  *
540  *		If successful, returns a new copy object.
541  */
542 static kern_return_t
vm_map_copyin_internal(vm_map_t src_map,vm_map_offset_t src_addr,vm_map_size_t len,boolean_t src_destroy,vm_map_copy_t * copy_result)543 vm_map_copyin_internal(
544 	vm_map_t	src_map,
545 	vm_map_offset_t	src_addr,
546 	vm_map_size_t	len,
547 	boolean_t	src_destroy,
548 	vm_map_copy_t	*copy_result)
549 {
550 	kern_return_t kr;
551 	vm_map_copy_t copy;
552 	vm_size_t size;
553 
554 	if ((vm_size_t) len != len) {
555 		/* "len" is too big and doesn't fit in a "vm_size_t" */
556 		return KERN_RESOURCE_SHORTAGE;
557 	}
558 	size =  (vm_size_t) (sizeof(struct vm_map_copy) + len);
559 	copy = (vm_map_copy_t) malloc(size, M_MACH_VM, M_NOWAIT|M_ZERO);
560 	if (copy == VM_MAP_COPY_NULL) {
561 		kr = KERN_RESOURCE_SHORTAGE;
562 		goto fail;
563 	}
564 	copy->type = VM_MAP_COPY_KERNEL_BUFFER;
565 	copy->size = len;
566 	copy->offset = 0;
567 	copy->cpy_kalloc_size = size;
568 	copy->cpy_kdata = (vm_offset_t) (copy + 1);
569 
570 	if (src_map == kernel_map) {
571 		memcpy((void *)copy->cpy_kdata, (void *)src_addr, len);
572 		free((void *)src_addr, M_MACH_VM);
573 	} else {
574 
575 		kr = copyinmap(src_map, src_addr, copy->cpy_kdata, (vm_size_t) len);
576 		if (kr != KERN_SUCCESS) {
577 			free(copy, M_MACH_VM);
578 			return kr;
579 		}
580 		if (src_destroy) {
581 			(void) vm_map_remove(
582 				src_map,
583 				trunc_page(src_addr),
584 				round_page(src_addr + len));
585 		}
586 	}
587 	*copy_result = copy;
588 	return KERN_SUCCESS;
589 fail:
590 	if (src_map == kernel_map)
591 		free((void *)src_addr, M_MACH_VM);
592 	return (kr);
593 }
594 
595 /*
596  *	Routine:	vm_map_copyout_kernel_buffer
597  *
598  *	Description:
599  *		Copy out data from a kernel buffer into space in the
600  *		destination map. The space may be otpionally dynamically
601  *		allocated.
602  *
603  *		If successful, consumes the copy object.
604  *		Otherwise, the caller is responsible for it.
605  */
606 static kern_return_t
vm_map_copyout_kernel_buffer(vm_map_t map,vm_offset_t * addr,vm_map_copy_t copy,boolean_t overwrite)607 vm_map_copyout_kernel_buffer(
608 	vm_map_t	map,
609 	vm_offset_t	*addr,	/* IN/OUT */
610 	vm_map_copy_t	copy,
611 	boolean_t	overwrite)
612 {
613 	kern_return_t kr = KERN_SUCCESS;
614 
615 	if (!overwrite) {
616 
617 		/*
618 		 * Allocate space in the target map for the data
619 		 */
620 		*addr = 0;
621 		kr = mach_vm_allocate(map, addr, round_page(copy->size), VM_FLAGS_ANYWHERE);
622 		if (kr != KERN_SUCCESS)
623 			return(kr);
624 	}
625 
626 	/*
627 	 * Copyout the data from the kernel buffer to the target map.
628 	 */
629 	if (current_map() == map) {
630 		/*
631 		 * If the target map is the current map, just do
632 		 * the copy.
633 		 */
634 		if (copyout((char *)copy->cpy_kdata, (char *)*addr,
635 				copy->size)) {
636 			kr = KERN_INVALID_ADDRESS;
637 		}
638 	}
639 	else {
640 		panic("unexpected map %p", map);
641 #if 0
642 		vm_map_t oldmap;
643 
644 		/*
645 		 * If the target map is another map, assume the
646 		 * target's address space identity for the duration
647 		 * of the copy.
648 		 */
649 		vm_map_reference(map);
650 		oldmap = vm_map_switch(map);
651 
652 		if (copyout((char *)copy->cpy_kdata, (char *)*addr,
653 				copy->size)) {
654 			kr = KERN_INVALID_ADDRESS;
655 		}
656 
657 		(void) vm_map_switch(oldmap);
658 		vm_map_deallocate(map);
659 #endif
660 		kr = KERN_NOT_SUPPORTED;
661 	}
662 
663 	free(copy, M_MACH_VM);
664 
665 	return(kr);
666 }
667 
668 
669 
670 /*
671  *	vm_map_copyin_object:
672  *
673  *	Create a copy object from an object.
674  *	Our caller donates an object reference.
675  */
676 
677 static kern_return_t
vm_map_copyin_object(vm_object_t object,vm_offset_t offset,vm_size_t size,vm_map_copy_t * copy_result)678 vm_map_copyin_object(
679 	vm_object_t	object,
680 	vm_offset_t	offset,		/* offset of region in object */
681 	vm_size_t	size,		/* size of region in object */
682 	vm_map_copy_t	*copy_result)	/* OUT */
683 {
684 	vm_map_copy_t	copy;		/* Resulting copy */
685 
686 	/*
687 	 *	We drop the object into a special copy object
688 	 *	that contains the object directly.
689 	 */
690 
691 	copy = (vm_map_copy_t) malloc(sizeof(vm_map_copy_t), M_MACH_VM, M_WAITOK|M_ZERO);
692 	copy->type = VM_MAP_COPY_OBJECT;
693 	copy->cpy_object = object;
694 
695 	copy->offset = offset;
696 	copy->size = size;
697 
698 	*copy_result = copy;
699 	return(KERN_SUCCESS);
700 }
701 
vm_map_copyin(vm_map_t src_map,vm_map_address_t src_addr,vm_map_size_t len,boolean_t src_destroy,vm_map_copy_t * copy_result)702 kern_return_t	vm_map_copyin(
703 				vm_map_t			src_map,
704 				vm_map_address_t	src_addr,
705 				vm_map_size_t		len,
706 				boolean_t			src_destroy,
707 				vm_map_copy_t		*copy_result)
708 {
709 	vm_map_entry_t	tmp_entry;	/* Result of last map lookup --
710 					 * in multi-level lookup, this
711 					 * entry contains the actual
712 					 * vm_object/offset.
713 					 */
714 #if 0
715 	vm_map_entry_t	new_entry = NULL;	/* Map entry for copy */
716 #endif
717 	vm_object_t object;
718 	vm_offset_t prev_end;
719 
720 	vm_offset_t	src_start;	/* Start of current entry --
721 					 * where copy is taking place now
722 					 */
723 	vm_offset_t src_end;
724 	vm_offset_t offset;
725 
726 	/*
727 	 * three possibilities:
728 	 * - len is less than  MSG_OOL_SIZE_SMALL:
729 	 *   allocate memory and copyin with header
730 	 * - len is greater but src_map is the special copy map:
731 	 *   allocate just a header and point at src_addr
732 	 * - len is greater:
733 	 *     lookup entry
734 	 *     while entry does not cover full range && entry changed:
735 	 *       simplify entry
736 	 *     if entry edges extend outside of range:
737 	 *       clip
738 	 *     if no object:
739 	 *       add object
740 	 *     reference object
741 	 *     if src_destroy is not true:
742 	 *       mark entry needs COW && NEEDS_COPY
743 	 *       pmap_protect range
744 	 *       create shadow object
745 	 *     else:
746 	 *       split object
747 	 *       delete entry from source map
748 	 *       if data is not aligned copy edge pages and insert
749 	 *         into source map
750 	 *     create map copy object w/ object
751 	 */
752 
753 
754 	if (len == 0) {
755 		*copy_result = VM_MAP_COPY_NULL;
756 		return(KERN_SUCCESS);
757 	}
758 
759 	src_start = trunc_page(src_addr);
760 	src_end = round_page(src_addr + len);
761 	if (src_end < src_addr)
762 		return KERN_INVALID_ADDRESS;
763 
764 	if (len < msg_ool_size_small || src_map == kernel_map)
765 		return vm_map_copyin_internal(src_map, src_addr, len,
766 										   src_destroy, copy_result);
767 
768 	/*
769 	 *	Find the beginning of the region.
770 	 */
771 	vm_map_lock(src_map);
772 
773 	if (!vm_map_lookup_entry(src_map, src_start, &tmp_entry)) {
774 		vm_map_unlock(src_map);
775 		return KERN_INVALID_ADDRESS;
776 	}
777 	prev_end = 0;
778 	while (prev_end != tmp_entry->end  && tmp_entry->end < src_end) {
779 		prev_end = tmp_entry->end;
780 		vm_map_simplify_entry(src_map, tmp_entry);
781 	}
782 	/* only handle single map entry for now */
783 	if (tmp_entry->end < src_end) {
784 		vm_map_unlock(src_map);
785 		return KERN_NOT_SUPPORTED;
786 	}
787 	object = tmp_entry->object.vm_object;
788 
789 	if (src_destroy) {
790 		offset = 0;
791 		vm_map_clip_start(src_map, tmp_entry, src_start);
792 		vm_map_clip_end(src_map, tmp_entry, src_end);
793 		VM_OBJECT_WLOCK(object);
794 		vm_object_reference_locked(object);
795 		vm_object_split(tmp_entry);
796 		object = tmp_entry->object.vm_object;
797 		tmp_entry->object.vm_object = NULL;
798 		vm_object_reference_locked(object);
799 		VM_OBJECT_WUNLOCK(object);
800 		vm_map_delete(src_map, src_start, src_end);
801 		vm_map_unlock(src_map);
802 	} else {
803 		offset = tmp_entry->offset;
804 		vm_map_unlock(src_map);
805 		vm_object_reference(object);
806 		vm_map_protect(src_map, src_start, src_end, tmp_entry->protection & ~VM_PROT_WRITE, 0);
807 		tmp_entry->eflags |= MAP_ENTRY_NEEDS_COPY | MAP_ENTRY_COW;
808 	}
809 
810 	vm_map_copyin_object(object, offset, src_end - src_start, copy_result);
811 	/* neither mach nor osx does anything to prevent information leakage
812 	 * in unaligned sends
813 	 */
814 	return KERN_SUCCESS;
815 }
816 
817 
818 
819 /*
820  *	Routine:	vm_map_copyout
821  *
822  *	Description:
823  *		Copy out a copy chain ("copy") into newly-allocated
824  *		space in the destination map.
825  *
826  *		If successful, consumes the copy object.
827  *		Otherwise, the caller is responsible for it.
828  */
829 
830 
831 kern_return_t
vm_map_copyout(vm_map_t dst_map,vm_map_address_t * dst_addr,vm_map_copy_t copy)832 vm_map_copyout(
833 	vm_map_t		dst_map,
834 	vm_map_address_t	*dst_addr,	/* OUT */
835 	vm_map_copy_t		copy)
836 {
837 	int cow;
838 	vm_object_t object;
839 
840 	*dst_addr = 0;
841 /*
842 	 *	Check for special kernel buffer allocated
843 	 *	by new_ipc_kmsg_copyin.
844 	 */
845 	if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
846 		return (vm_map_copyout_kernel_buffer(dst_map, dst_addr,
847 						    copy, FALSE));
848 	}
849 	if (copy->type == VM_MAP_COPY_OBJECT) {
850 		*dst_addr = 0;
851 		object = copy->cpy_object;
852 		cow = object->ref_count > 1 ? MAP_COPY_ON_WRITE : 0;
853 		printf("object: %p size: %ld ref_count: %d type: %d flags: %x resident_page_count: %d\n",
854 			   object, object->size, object->ref_count, object->type, object->flags,
855 			   object->resident_page_count);
856 
857 		return vm_map_find(dst_map, copy->cpy_object, copy->offset,
858 		    dst_addr, round_page(copy->size), 0, VMFS_OPTIMAL_SPACE,
859 		    VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE,
860 		    cow);
861 	}
862 	return KERN_NOT_SUPPORTED;
863 #if 0
864 	return vm_map_copyout_internal(dst_map, dst_addr, copy,
865 				       TRUE, /* consume_on_success */
866 				       VM_PROT_DEFAULT,
867 				       VM_PROT_ALL,
868 				       VM_INHERIT_DEFAULT);
869 #endif
870 }
871 
872 #if 0
873 static kern_return_t
874 vm_map_copyout_internal(
875 	register vm_map_t	dst_map,
876 	vm_offset_t		*dst_addr,	/* OUT */
877 	register vm_map_copy_t	copy,
878 	boolean_t consume_on_success,
879 	vm_prot_t cur_protection,
880 	vm_prot_t max_protection,
881 	vm_inherit_t inheritance)
882 {
883 	vm_size_t	size;
884 	vm_size_t	adjustment;
885 	vm_offset_t	start;
886 	vm_offset_t	vm_copy_start;
887 	vm_map_entry_t	last;
888 	vm_map_entry_t	entry;
889 
890 	/*
891 	 *	Check for null copy object.
892 	 */
893 
894 	if (copy == VM_MAP_COPY_NULL) {
895 		*dst_addr = 0;
896 		return(KERN_SUCCESS);
897 	}
898 
899 	/*
900 	 *	Check for special copy object, created
901 	 *	by vm_map_copyin_object.
902 	 */
903 
904 	if (copy->type == VM_MAP_COPY_OBJECT) {
905 		vm_object_t object = copy->cpy_object;
906 		kern_return_t kr;
907 		vm_size_t offset;
908 
909 		offset = trunc_page(copy->offset);
910 		size = round_page(copy->size + copy->offset - offset);
911 		*dst_addr = 0;
912 		kr = vm_map_enter(dst_map, dst_addr, size,
913 				  (vm_offset_t) 0, TRUE,
914 				  object, offset, FALSE,
915 				  VM_PROT_DEFAULT, VM_PROT_ALL,
916 				  VM_INHERIT_DEFAULT);
917 		if (kr != KERN_SUCCESS)
918 			return(kr);
919 		/* Account for non-pagealigned copy object */
920 		*dst_addr += copy->offset - offset;
921 		uma_zfree(vm_map_copy_zone, copy);
922 		return(KERN_SUCCESS);
923 	}
924 
925 	/*
926 	 *	Check for special kernel buffer allocated
927 	 *	by new_ipc_kmsg_copyin.
928 	 */
929 
930 	if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
931 		return(vm_map_copyout_kernel_buffer(dst_map, dst_addr,
932 						    copy, FALSE));
933 	}
934 
935 	/*
936 	 *	Find space for the data
937 	 */
938 
939 	vm_copy_start = trunc_page(copy->offset);
940 	size =	round_page(copy->offset + copy->size) - vm_copy_start;
941 
942  StartAgain: ;
943 
944 	vm_map_lock(dst_map);
945 	assert(first_free_is_valid(dst_map));
946 	start = ((last = dst_map->first_free) == vm_map_to_entry(dst_map)) ?
947 		vm_map_min(dst_map) : last->vme_end;
948 
949 	while (TRUE) {
950 		vm_map_entry_t	next = last->vme_next;
951 		vm_offset_t	end = start + size;
952 
953 		if ((end > dst_map->max_offset) || (end < start)) {
954 			if (dst_map->wait_for_space) {
955 				if (size <= (dst_map->max_offset - dst_map->min_offset)) {
956 					assert_wait((event_t) dst_map, TRUE);
957 					vm_map_unlock(dst_map);
958 					thread_block((void (*)(void))0);
959 					goto StartAgain;
960 				}
961 			}
962 			vm_map_unlock(dst_map);
963 			return(KERN_NO_SPACE);
964 		}
965 
966 		if ((next == vm_map_to_entry(dst_map)) ||
967 		    (next->vme_start >= end))
968 			break;
969 
970 		last = next;
971 		start = last->vme_end;
972 	}
973 
974 	/*
975 	 *	Since we're going to just drop the map
976 	 *	entries from the copy into the destination
977 	 *	map, they must come from the same pool.
978 	 */
979 
980 	if (copy->cpy_hdr.entries_pageable != dst_map->hdr.entries_pageable) {
981 	    /*
982 	     * Mismatches occur when dealing with the default
983 	     * pager.
984 	     */
985 	    zone_t		old_zone;
986 	    vm_map_entry_t	next, new;
987 
988 	    /*
989 	     * Find the zone that the copies were allocated from
990 	     */
991 	    old_zone = (copy->cpy_hdr.entries_pageable)
992 			? vm_map_entry_zone
993 			: vm_map_kentry_zone;
994 	    entry = vm_map_copy_first_entry(copy);
995 
996 	    /*
997 	     * Reinitialize the copy so that vm_map_copy_entry_link
998 	     * will work.
999 	     */
1000 	    copy->cpy_hdr.nentries = 0;
1001 	    copy->cpy_hdr.entries_pageable = dst_map->hdr.entries_pageable;
1002 	    vm_map_copy_first_entry(copy) =
1003 	     vm_map_copy_last_entry(copy) =
1004 		vm_map_copy_to_entry(copy);
1005 
1006 	    /*
1007 	     * Copy each entry.
1008 	     */
1009 	    while (entry != vm_map_copy_to_entry(copy)) {
1010 		new = vm_map_copy_entry_create(copy);
1011 		vm_map_entry_copy_full(new, entry);
1012 		vm_map_copy_entry_link(copy,
1013 				vm_map_copy_last_entry(copy),
1014 				new);
1015 		next = entry->vme_next;
1016 		uma_zfree(old_zone, entry);
1017 		entry = next;
1018 	    }
1019 	}
1020 
1021 	/*
1022 	 *	Adjust the addresses in the copy chain, and
1023 	 *	reset the region attributes.
1024 	 */
1025 
1026 	adjustment = start - vm_copy_start;
1027 	for (entry = vm_map_copy_first_entry(copy);
1028 	     entry != vm_map_copy_to_entry(copy);
1029 	     entry = entry->vme_next) {
1030 		entry->vme_start += adjustment;
1031 		entry->vme_end += adjustment;
1032 
1033 		entry->inheritance = VM_INHERIT_DEFAULT;
1034 		entry->protection = VM_PROT_DEFAULT;
1035 		entry->max_protection = VM_PROT_ALL;
1036 		entry->behavior = VM_BEHAVIOR_DEFAULT;
1037 
1038 		/*
1039 		 * If the entry is now wired,
1040 		 * map the pages into the destination map.
1041 		 */
1042 		if (entry->wired_count != 0) {
1043 		    register vm_offset_t va;
1044 		    vm_offset_t		 offset;
1045 		    register vm_object_t object;
1046 
1047 		    object = entry->object.vm_object;
1048 		    offset = entry->offset;
1049 		    va = entry->vme_start;
1050 
1051 		    pmap_pageable(dst_map->pmap,
1052 				  entry->vme_start,
1053 				  entry->vme_end,
1054 				  TRUE);
1055 
1056 		    while (va < entry->vme_end) {
1057 			register vm_page_t	m;
1058 
1059 			/*
1060 			 * Look up the page in the object.
1061 			 * Assert that the page will be found in the
1062 			 * top object:
1063 			 * either
1064 			 *	the object was newly created by
1065 			 *	vm_object_copy_slowly, and has
1066 			 *	copies of all of the pages from
1067 			 *	the source object
1068 			 * or
1069 			 *	the object was moved from the old
1070 			 *	map entry; because the old map
1071 			 *	entry was wired, all of the pages
1072 			 *	were in the top-level object.
1073 			 *	(XXX not true if we wire pages for
1074 			 *	 reading)
1075 			 */
1076 			vm_object_lock(object);
1077 			vm_object_paging_begin(object);
1078 
1079 			m = vm_page_lookup(object, offset);
1080 			if (m == VM_PAGE_NULL || m->wire_count == 0 ||
1081 			    m->absent)
1082 			    panic("vm_map_copyout: wiring 0x%x", m);
1083 
1084 			m->busy = TRUE;
1085 			vm_object_unlock(object);
1086 
1087 			PMAP_ENTER(dst_map->pmap, va, m,
1088 				   entry->protection, TRUE);
1089 
1090 			vm_object_lock(object);
1091 			PAGE_WAKEUP_DONE(m);
1092 			/* the page is wired, so we don't have to activate */
1093 			vm_object_paging_end(object);
1094 			vm_object_unlock(object);
1095 
1096 			offset += PAGE_SIZE;
1097 			va += PAGE_SIZE;
1098 		    }
1099 		}
1100 		else if (size <= vm_map_aggressive_enter_max) {
1101 
1102 			register vm_offset_t	va;
1103 			vm_offset_t		offset;
1104 			register vm_object_t	object;
1105 			vm_prot_t		prot;
1106 
1107 			object = entry->object.vm_object;
1108 			if (object != VM_OBJECT_NULL) {
1109 
1110 				offset = entry->offset;
1111 				va = entry->vme_start;
1112 				while (va < entry->vme_end) {
1113 					register vm_page_t	m;
1114 
1115 					/*
1116 					 * Look up the page in the object.
1117 					 * Assert that the page will be found
1118 					 * in the top object if at all...
1119 					 */
1120 					vm_object_lock(object);
1121 					vm_object_paging_begin(object);
1122 
1123 					if (((m = vm_page_lookup(object,
1124 								 offset))
1125 					     != VM_PAGE_NULL) &&
1126 					    !m->busy && !m->fictitious &&
1127 					    !m->absent && !m->error) {
1128 						m->busy = TRUE;
1129 						vm_object_unlock(object);
1130 
1131 						/* honor cow obligations */
1132 						prot = entry->protection;
1133 						if (entry->needs_copy)
1134 							prot &= ~VM_PROT_WRITE;
1135 
1136 						PMAP_ENTER(dst_map->pmap, va,
1137 							   m, prot, FALSE);
1138 
1139 						vm_object_lock(object);
1140 						vm_page_lock_queues();
1141 						if (!m->active && !m->inactive)
1142 							vm_page_activate(m);
1143 						vm_page_unlock_queues();
1144 						PAGE_WAKEUP_DONE(m);
1145 					}
1146 					vm_object_paging_end(object);
1147 					vm_object_unlock(object);
1148 
1149 					offset += PAGE_SIZE;
1150 					va += PAGE_SIZE;
1151 				}
1152 			}
1153 		}
1154 	}
1155 
1156 	/*
1157 	 *	Correct the page alignment for the result
1158 	 */
1159 
1160 	*dst_addr = start + (copy->offset - vm_copy_start);
1161 
1162 	/*
1163 	 *	Update the hints and the map size
1164 	 */
1165 
1166 	SAVE_HINT(dst_map, vm_map_copy_last_entry(copy));
1167 
1168 	dst_map->size += size;
1169 
1170 	/*
1171 	 *	Link in the copy
1172 	 */
1173 
1174 	vm_map_copy_insert(dst_map, last, copy);
1175 
1176 	vm_map_unlock(dst_map);
1177 
1178 	/*
1179 	 * XXX	If wiring_required, call vm_map_pageable
1180 	 */
1181 
1182 	return(KERN_SUCCESS);
1183 }
1184 #endif
1185 /*
1186  *	Routine:	vm_map_copy_discard
1187  *
1188  *	Description:
1189  *		Dispose of a map copy object (returned by
1190  *		vm_map_copyin).
1191  */
1192 void
vm_map_copy_discard(vm_map_copy_t copy)1193 vm_map_copy_discard(
1194 	vm_map_copy_t	copy)
1195 {
1196 
1197 	if (copy == VM_MAP_COPY_NULL)
1198 		return;
1199 
1200 	if (copy->type == VM_MAP_COPY_OBJECT)
1201 		vm_object_deallocate(copy->cpy_object);
1202 	free(copy, M_MACH_VM);
1203 }
1204 
1205 kern_return_t
vm_map_copy_overwrite(vm_map_t dst_map,vm_map_address_t dst_addr,vm_map_copy_t copy,boolean_t interruptible)1206 vm_map_copy_overwrite(vm_map_t                dst_map,
1207 					  vm_map_address_t        dst_addr,
1208 					  vm_map_copy_t           copy,
1209 					  boolean_t               interruptible)
1210 {
1211 	return (KERN_NOT_SUPPORTED);
1212 }
1213 
1214 int
mach_vm_behavior_set(vm_map_t target_task,mach_vm_address_t address,mach_vm_size_t size,vm_behavior_t new_behavior)1215 mach_vm_behavior_set(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, vm_behavior_t new_behavior)
1216 {
1217 
1218 	return (KERN_NOT_SUPPORTED);
1219 }
1220 
1221 int
mach_vm_page_info(vm_map_t target_task,mach_vm_address_t address,vm_page_info_flavor_t flavor,vm_page_info_t info,mach_msg_type_number_t * infoCnt)1222 mach_vm_page_info(vm_map_t target_task, mach_vm_address_t address,
1223 				  vm_page_info_flavor_t flavor, vm_page_info_t info,
1224 				  mach_msg_type_number_t *infoCnt)
1225 {
1226 
1227 		return (KERN_NOT_SUPPORTED);
1228 }
1229 
1230 int
mach_vm_page_query(vm_map_t target_map,mach_vm_offset_t offset,integer_t * disposition,integer_t * ref_count)1231 mach_vm_page_query(
1232 	vm_map_t target_map,
1233 	mach_vm_offset_t offset,
1234 	integer_t *disposition,
1235 	integer_t *ref_count
1236 )
1237 {
1238 
1239 		return (KERN_NOT_SUPPORTED);
1240 }
1241 
1242 int
mach_vm_purgable_control(vm_map_t target_task,mach_vm_address_t address,vm_purgable_t control,int * state)1243 mach_vm_purgable_control(
1244 	vm_map_t target_task,
1245 	mach_vm_address_t address,
1246 	vm_purgable_t control,
1247 	int *state
1248 	)
1249 {
1250 
1251 	return (KERN_NOT_SUPPORTED);
1252 }
1253 
1254 int
mach_vm_read_list(vm_map_t target_task,mach_vm_read_entry_t data_list,natural_t count)1255 mach_vm_read_list(
1256 	vm_map_t target_task,
1257 	mach_vm_read_entry_t data_list,
1258 	natural_t count
1259 	)
1260 {
1261 	return (KERN_NOT_SUPPORTED);
1262 }
1263 
1264 
1265 int
vm_read_list(vm_map_t target_task,vm_read_entry_t data_list,natural_t count)1266 vm_read_list(
1267 	vm_map_t target_task,
1268 	vm_read_entry_t data_list,
1269 	natural_t count
1270 	)
1271 {
1272 	return (KERN_NOT_SUPPORTED);
1273 }
1274 
1275 int
mach_vm_read_overwrite(vm_map_t target_task,mach_vm_address_t address,mach_vm_size_t size,mach_vm_address_t data,mach_vm_size_t * outsize)1276 mach_vm_read_overwrite(
1277 	vm_map_t target_task,
1278 	mach_vm_address_t address,
1279 	mach_vm_size_t size,
1280 	mach_vm_address_t data,
1281 	mach_vm_size_t *outsize
1282 )
1283 {
1284 	return (KERN_NOT_SUPPORTED);
1285 }
1286 
1287 int
mach_vm_region(vm_map_t target_task,mach_vm_address_t * address,mach_vm_size_t * size,vm_region_flavor_t flavor,vm_region_info_t info,mach_msg_type_number_t * infoCnt,mach_port_t * object_name)1288 mach_vm_region(
1289 	vm_map_t target_task,
1290 	mach_vm_address_t *address,
1291 	mach_vm_size_t *size,
1292 	vm_region_flavor_t flavor,
1293 	vm_region_info_t info,
1294 	mach_msg_type_number_t *infoCnt,
1295 	mach_port_t *object_name
1296 	)
1297 {
1298 	/*
1299 	 * MACH_VM_REGION_BASIC_INFO is the only
1300 	 * supported flavor in Darwin.
1301 	 */
1302 
1303 	return (KERN_NOT_SUPPORTED);
1304 }
1305 
1306 int
mach_vm_region_info(vm_map_t task,vm_address_t address,vm_info_region_t * region,vm_info_object_array_t * objects,mach_msg_type_number_t * objectsCnt)1307 mach_vm_region_info(
1308 	vm_map_t task,
1309 	vm_address_t address,
1310 	vm_info_region_t *region,
1311 	vm_info_object_array_t *objects,
1312 	mach_msg_type_number_t *objectsCnt
1313 )
1314 {
1315 	return (KERN_NOT_SUPPORTED);
1316 }
1317 
1318 int
mach_vm_region_info_64(vm_map_t task,vm_address_t address,vm_info_region_64_t * region,vm_info_object_array_t * objects,mach_msg_type_number_t * objectsCnt)1319 mach_vm_region_info_64(
1320 	vm_map_t task,
1321 	vm_address_t address,
1322 	vm_info_region_64_t *region,
1323 	vm_info_object_array_t *objects,
1324 	mach_msg_type_number_t *objectsCnt
1325 )
1326 {
1327 	return (KERN_NOT_SUPPORTED);
1328 }
1329 
1330 int
mach_vm_region_recurse(vm_map_t target_task,mach_vm_address_t * address,mach_vm_size_t * size,natural_t * nesting_depth,vm_region_recurse_info_t info,mach_msg_type_number_t * infoCnt)1331 mach_vm_region_recurse(
1332 	vm_map_t target_task,
1333 	mach_vm_address_t *address,
1334 	mach_vm_size_t *size,
1335 	natural_t *nesting_depth,
1336 	vm_region_recurse_info_t info,
1337 	mach_msg_type_number_t *infoCnt
1338 	)
1339 {
1340 	return (KERN_NOT_SUPPORTED);
1341 }
1342 
1343 int
mach_vm_mapped_pages_info(vm_map_t task,page_address_array_t * pages,mach_msg_type_number_t * pagesCnt)1344 mach_vm_mapped_pages_info(
1345 	vm_map_t task,
1346 	page_address_array_t *pages,
1347 	mach_msg_type_number_t *pagesCnt
1348 )
1349 {
1350 	return (KERN_NOT_SUPPORTED);
1351 }
1352 
1353 
1354 int
mach_vm_remap(vm_map_t target_task,mach_vm_address_t * target_address,mach_vm_size_t size,mach_vm_offset_t mask,int flags,vm_map_t src_task,mach_vm_address_t src_address,boolean_t copy,vm_prot_t * cur_protection,vm_prot_t * max_protection,vm_inherit_t inheritance)1355 mach_vm_remap(
1356 	vm_map_t target_task,
1357 	mach_vm_address_t *target_address,
1358 	mach_vm_size_t size,
1359 	mach_vm_offset_t mask,
1360 	int flags,
1361 	vm_map_t src_task,
1362 	mach_vm_address_t src_address,
1363 	boolean_t copy,
1364 	vm_prot_t *cur_protection,
1365 	vm_prot_t *max_protection,
1366 	vm_inherit_t inheritance
1367 	)
1368 {
1369 	return (KERN_NOT_SUPPORTED);
1370 }
1371 
1372 int
mach_vm_wire(host_priv_t host_priv,vm_map_t task,mach_vm_address_t address,mach_vm_size_t size,vm_prot_t desired_access)1373 mach_vm_wire(
1374 	host_priv_t host_priv,
1375 	vm_map_t task,
1376 	mach_vm_address_t address,
1377 	mach_vm_size_t size,
1378 	vm_prot_t desired_access
1379 )
1380 {
1381 	return (KERN_NOT_SUPPORTED);
1382 }
1383 
1384 int
mach_vm_wire_32(host_priv_t host_priv,vm_map_t task,vm_address_t address,vm_size_t size,vm_prot_t desired_access)1385 mach_vm_wire_32(
1386 	host_priv_t host_priv,
1387 	vm_map_t task,
1388 	vm_address_t address,
1389 	vm_size_t size,
1390 	vm_prot_t desired_access
1391 )
1392 {
1393 	return (KERN_NOT_SUPPORTED);
1394 }
1395 
1396 int
task_wire(vm_map_t target_task,boolean_t must_wire)1397 task_wire(vm_map_t target_task, boolean_t must_wire)
1398 {
1399 
1400 	return (KERN_NOT_SUPPORTED);
1401 }
1402 
1403 int
vm_allocate_cpm(host_priv_t host_priv,vm_map_t task,vm_address_t * address,vm_size_t size,int flags)1404 vm_allocate_cpm
1405 (
1406 	host_priv_t host_priv,
1407 	vm_map_t task,
1408 	vm_address_t *address,
1409 	vm_size_t size,
1410 	int flags
1411 )
1412 {
1413 
1414 	return (KERN_NOT_SUPPORTED);
1415 }
1416