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