1 /* $NetBSD: mach_vm.c,v 1.60 2008/04/28 20:23:45 martin Exp $ */
4 * Copyright (c) 2002-2003, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: mach_vm.c,v 1.60 2008/04/28 20:23:45 martin Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/mount.h>
41 #include <sys/malloc.h>
42 #include <sys/vnode.h>
44 #include <sys/filedesc.h>
45 #include <sys/ktrace.h>
47 #include <sys/syscallargs.h>
49 #include <uvm/uvm_prot.h>
50 #include <uvm/uvm_map.h>
51 #include <uvm/uvm_extern.h>
53 #include <compat/mach/mach_types.h>
54 #include <compat/mach/mach_message.h>
55 #include <compat/mach/mach_clock.h>
56 #include <compat/mach/mach_vm.h>
57 #include <compat/mach/mach_errno.h>
58 #include <compat/mach/mach_port.h>
59 #include <compat/mach/mach_services.h>
60 #include <compat/mach/mach_syscallargs.h>
63 mach_vm_map(struct mach_trap_args
*args
)
65 mach_vm_map_request_t
*req
= args
->smsg
;
66 mach_vm_map_reply_t
*rep
= args
->rmsg
;
67 size_t *msglen
= args
->rsize
;
68 struct lwp
*tl
= args
->tl
;
69 struct proc
*tp
= tl
->l_proc
;
70 struct sys_mmap_args cup
;
76 printf("mach_vm_map(addr = %p, size = 0x%08lx, obj = 0x%x, "
77 "mask = 0x%08lx, flags = 0x%x, offset = 0x%08llx, "
78 "copy = %d, cur_prot = 0x%x, max_prot = 0x%x, inh = 0x%x);\n",
79 (void *)req
->req_address
, (long)req
->req_size
, req
->req_object
.name
,
80 (long)req
->req_mask
, req
->req_flags
, (off_t
)req
->req_offset
,
81 req
->req_copy
, req
->req_cur_protection
, req
->req_max_protection
,
85 /* XXX Darwin fails on mapping a page at address 0 */
86 if (req
->req_address
== 0)
87 return mach_msg_error(args
, ENOMEM
);
89 req
->req_size
= round_page(req
->req_size
);
91 /* Where Mach uses 0x00ff, we use 0x0100 */
92 if ((req
->req_mask
& (req
->req_mask
+ 1)) || (req
->req_mask
== 0))
97 if (req
->req_flags
& MACH_VM_FLAGS_ANYWHERE
) {
98 SCARG(&cup
, flags
) = MAP_ANON
;
101 SCARG(&cup
, flags
) = MAP_ANON
| MAP_FIXED
;
106 * Use uvm_map_findspace to find a place which conforms to the
107 * requested alignement.
109 vm_map_lock(&tp
->p_vmspace
->vm_map
);
110 ret
= uvm_map_findspace(&tp
->p_vmspace
->vm_map
,
111 trunc_page(req
->req_address
), req
->req_size
, &addr
,
112 NULL
, 0, req
->req_mask
, flags
);
113 vm_map_unlock(&tp
->p_vmspace
->vm_map
);
116 return mach_msg_error(args
, ENOMEM
);
118 switch(req
->req_inherance
) {
119 case MACH_VM_INHERIT_SHARE
:
120 SCARG(&cup
, flags
) |= MAP_INHERIT
;
122 case MACH_VM_INHERIT_COPY
:
123 SCARG(&cup
, flags
) |= MAP_COPY
;
125 case MACH_VM_INHERIT_NONE
:
127 case MACH_VM_INHERIT_DONATE_COPY
:
129 uprintf("mach_vm_map: unsupported inherance flag %d\n",
134 SCARG(&cup
, addr
) = (void *)addr
;
135 SCARG(&cup
, len
) = req
->req_size
;
136 SCARG(&cup
, prot
) = req
->req_cur_protection
;
137 SCARG(&cup
, fd
) = -1; /* XXX For now, no object mapping */
138 SCARG(&cup
, pos
) = req
->req_offset
;
140 if ((error
= sys_mmap(tl
, &cup
, &rep
->rep_retval
)) != 0)
141 return mach_msg_error(args
, error
);
143 *msglen
= sizeof(*rep
);
144 mach_set_header(rep
, req
, *msglen
);
145 mach_set_trailer(rep
, *msglen
);
151 mach_vm_allocate(struct mach_trap_args
*args
)
153 mach_vm_allocate_request_t
*req
= args
->smsg
;
154 mach_vm_allocate_reply_t
*rep
= args
->rmsg
;
155 size_t *msglen
= args
->rsize
;
156 struct lwp
*tl
= args
->tl
;
157 struct proc
*tp
= tl
->l_proc
;
158 struct sys_mmap_args cup
;
163 addr
= req
->req_address
;
164 size
= req
->req_size
;
167 printf("mach_vm_allocate(addr = %p, size = 0x%08x);\n",
172 * Avoid mappings at address zero: it should
173 * be a "red zone" with nothing mapped on it.
176 if (req
->req_flags
& MACH_VM_FLAGS_ANYWHERE
)
179 return mach_msg_error(args
, EINVAL
);
181 printf("mach_vm_allocate: trying addr = %p\n", (void *)addr
);
185 size
= round_page(size
);
186 if (req
->req_flags
& MACH_VM_FLAGS_ANYWHERE
)
187 addr
= vm_map_min(&tp
->p_vmspace
->vm_map
);
189 addr
= trunc_page(addr
);
191 if (((addr
+ size
) > vm_map_max(&tp
->p_vmspace
->vm_map
)) ||
192 ((addr
+ size
) <= addr
))
193 addr
= vm_map_min(&tp
->p_vmspace
->vm_map
);
198 SCARG(&cup
, addr
) = (void *)addr
;
199 SCARG(&cup
, len
) = size
;
200 SCARG(&cup
, prot
) = PROT_READ
| PROT_WRITE
;
201 SCARG(&cup
, flags
) = MAP_ANON
;
202 if ((req
->req_flags
& MACH_VM_FLAGS_ANYWHERE
) == 0)
203 SCARG(&cup
, flags
) |= MAP_FIXED
;
204 SCARG(&cup
, fd
) = -1;
205 SCARG(&cup
, pos
) = 0;
207 if ((error
= sys_mmap(tl
, &cup
, &rep
->rep_address
)) != 0)
208 return mach_msg_error(args
, error
);
210 printf("vm_allocate: success at %p\n", (void *)rep
->rep_address
);
214 *msglen
= sizeof(*rep
);
215 mach_set_header(rep
, req
, *msglen
);
219 mach_set_trailer(rep
, *msglen
);
225 mach_vm_deallocate(struct mach_trap_args
*args
)
227 mach_vm_deallocate_request_t
*req
= args
->smsg
;
228 mach_vm_deallocate_reply_t
*rep
= args
->rmsg
;
229 size_t *msglen
= args
->rsize
;
230 struct lwp
*tl
= args
->tl
;
231 struct sys_munmap_args cup
;
235 printf("mach_vm_deallocate(addr = %p, size = 0x%08lx);\n",
236 (void *)req
->req_address
, (long)req
->req_size
);
239 SCARG(&cup
, addr
) = (void *)req
->req_address
;
240 SCARG(&cup
, len
) = req
->req_size
;
242 if ((error
= sys_munmap(tl
, &cup
, &rep
->rep_retval
)) != 0)
243 return mach_msg_error(args
, error
);
245 *msglen
= sizeof(*rep
);
246 mach_set_header(rep
, req
, *msglen
);
247 mach_set_trailer(rep
, *msglen
);
253 * XXX This server message Id clashes with bootstrap_look_up.
254 * Is there a way to resolve this easily?
258 mach_vm_wire(struct mach_trap_args
*args
)
260 mach_vm_wire_request_t
*req
= args
->smsg
;
261 mach_vm_wire_reply_t
*rep
= args
->rmsg
;
262 size_t *msglen
= args
->rsize
;
263 struct lwp
*tl
= args
->tl
;
268 printf("mach_vm_wire(addr = %p, size = 0x%08x, prot = 0x%x);\n",
269 (void *)req
->req_address
, req
->req_size
, req
->req_access
);
272 memset(&rep
, 0, sizeof(*rep
));
274 if ((req
->req_access
& ~VM_PROT_ALL
) != 0)
275 return mach_msg_error(args
, EINVAL
);
278 * Mach maintains a count of how many times a page is wired
279 * and unwire it once the count is zero. We cannot do that yet.
281 if (req
->req_access
== 0) {
282 struct sys_munlock_args cup
;
284 SCARG(&cup
, addr
) = (void *)req
->req_address
;
285 SCARG(&cup
, len
) = req
->req_size
;
286 error
= sys_munlock(tl
, &cup
, &retval
);
288 struct sys_mlock_args cup
;
290 SCARG(&cup
, addr
) = (void *)req
->req_address
;
291 SCARG(&cup
, len
) = req
->req_size
;
292 error
= sys_mlock(tl
, &cup
, &retval
);
295 return mach_msg_error(args
, error
);
297 if ((error
= uvm_map_protect(&tl
->l_proc
->p_vmspace
->vm_map
,
298 req
->req_address
, req
->req_address
+ req
->req_size
,
299 req
->req_access
, 0)) != 0)
300 return mach_msg_error(args
, error
);
302 *msglen
= sizeof(*rep
);
303 mach_set_header(rep
, req
, *msglen
);
304 mach_set_trailer(rep
, *msglen
);
311 mach_vm_protect(struct mach_trap_args
*args
)
313 mach_vm_protect_request_t
*req
= args
->smsg
;
314 mach_vm_protect_reply_t
*rep
= args
->rmsg
;
315 size_t *msglen
= args
->rsize
;
316 struct lwp
*tl
= args
->tl
;
317 struct sys_mprotect_args cup
;
321 SCARG(&cup
, addr
) = (void *)req
->req_addr
;
322 SCARG(&cup
, len
) = req
->req_size
;
323 SCARG(&cup
, prot
) = req
->req_prot
;
325 if ((error
= sys_mprotect(tl
, &cup
, &retval
)) != 0)
326 return mach_msg_error(args
, error
);
328 *msglen
= sizeof(*rep
);
329 mach_set_header(rep
, req
, *msglen
);
330 mach_set_trailer(rep
, *msglen
);
336 mach_sys_map_fd(struct lwp
*l
, const struct mach_sys_map_fd_args
*uap
, register_t
*retval
)
340 syscallarg(mach_vm_offset_t) offset;
341 syscallarg(mach_vm_offset_t *) va;
342 syscallarg(mach_boolean_t) findspace;
343 syscallarg(mach_vm_size_t) size;
347 struct exec_vmcmd evc
;
348 struct vm_map_entry
*ret
;
349 struct proc
*p
= l
->l_proc
;
351 struct sys_munmap_args cup
;
355 if ((error
= copyin(SCARG(uap
, va
), (void *)&va
, sizeof(va
))) != 0)
358 if (SCARG(uap
, findspace
) == 0) {
359 /* Make some free space XXX probably not The Right Way */
360 SCARG(&cup
, addr
) = va
;
361 SCARG(&cup
, len
) = SCARG(uap
, size
);
362 (void)sys_munmap(l
, &cup
, &dontcare
);
365 fp
= fd_getfile(SCARG(uap
, fd
));
373 printf("vm_map_fd: addr = %p len = 0x%08lx\n",
374 va
, (long)SCARG(uap
, size
));
376 memset(&evc
, 0, sizeof(evc
));
377 evc
.ev_addr
= (u_long
)va
;
378 evc
.ev_len
= SCARG(uap
, size
);
379 evc
.ev_prot
= VM_PROT_ALL
;
380 evc
.ev_flags
= SCARG(uap
, findspace
) ? 0 : VMCMD_FIXED
;
381 evc
.ev_proc
= vmcmd_map_readvn
;
382 evc
.ev_offset
= SCARG(uap
, offset
);
385 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
386 if ((error
= (*evc
.ev_proc
)(l
, &evc
)) != 0) {
390 printf("mach_sys_map_fd: mapping at %p failed\n", va
);
393 if (SCARG(uap
, findspace
) == 0)
396 vm_map_lock(&p
->p_vmspace
->vm_map
);
397 if ((ret
= uvm_map_findspace(&p
->p_vmspace
->vm_map
,
398 vm_map_min(&p
->p_vmspace
->vm_map
), evc
.ev_len
,
399 (vaddr_t
*)&evc
.ev_addr
, NULL
, 0, PAGE_SIZE
, 0)) == NULL
) {
400 vm_map_unlock(&p
->p_vmspace
->vm_map
);
403 vm_map_unlock(&p
->p_vmspace
->vm_map
);
405 va
= (void *)evc
.ev_addr
;
407 memset(&evc
, 0, sizeof(evc
));
408 evc
.ev_addr
= (u_long
)va
;
409 evc
.ev_len
= SCARG(uap
, size
);
410 evc
.ev_prot
= VM_PROT_ALL
;
412 evc
.ev_proc
= vmcmd_map_readvn
;
413 evc
.ev_offset
= SCARG(uap
, offset
);
417 printf("mach_sys_map_fd: trying at %p\n", va
);
419 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
420 if ((error
= (*evc
.ev_proc
)(l
, &evc
)) != 0)
425 fd_putfile(SCARG(uap
, fd
));
427 printf("mach_sys_map_fd: mapping at %p\n", (void *)evc
.ev_addr
);
430 va
= (mach_vm_offset_t
*)evc
.ev_addr
;
432 if ((error
= copyout((void *)&va
, SCARG(uap
, va
), sizeof(va
))) != 0)
441 fd_putfile(SCARG(uap
, fd
));
443 printf("mach_sys_map_fd: mapping at %p failed, error = %d\n",
444 (void *)evc
.ev_addr
, error
);
450 mach_vm_inherit(struct mach_trap_args
*args
)
452 mach_vm_inherit_request_t
*req
= args
->smsg
;
453 mach_vm_inherit_reply_t
*rep
= args
->rmsg
;
454 size_t *msglen
= args
->rsize
;
455 struct lwp
*tl
= args
->tl
;
456 struct sys_minherit_args cup
;
460 SCARG(&cup
, addr
) = (void *)req
->req_addr
;
461 SCARG(&cup
, len
) = req
->req_size
;
462 /* Flags map well between Mach and NetBSD */
463 SCARG(&cup
, inherit
) = req
->req_inh
;
465 if ((error
= sys_minherit(tl
, &cup
, &retval
)) != 0)
466 return mach_msg_error(args
, error
);
468 *msglen
= sizeof(*rep
);
469 mach_set_header(rep
, req
, *msglen
);
470 mach_set_trailer(rep
, *msglen
);
476 mach_make_memory_entry_64(struct mach_trap_args
*args
)
478 mach_make_memory_entry_64_request_t
*req
= args
->smsg
;
479 mach_make_memory_entry_64_reply_t
*rep
= args
->rmsg
;
480 size_t *msglen
= args
->rsize
;
481 struct lwp
*l
= args
->l
;
482 struct lwp
*tl
= args
->tl
;
483 struct mach_port
*mp
;
484 struct mach_right
*mr
;
485 struct mach_memory_entry
*mme
;
487 printf("mach_make_memory_entry_64, offset 0x%lx, size 0x%lx\n",
488 (u_long
)req
->req_offset
, (u_long
)req
->req_size
);
490 mp
= mach_port_get();
491 mp
->mp_flags
|= (MACH_MP_INKERNEL
| MACH_MP_DATA_ALLOCATED
);
492 mp
->mp_datatype
= MACH_MP_MEMORY_ENTRY
;
494 mme
= malloc(sizeof(*mme
), M_EMULDATA
, M_WAITOK
);
495 mme
->mme_proc
= tl
->l_proc
;
496 mme
->mme_offset
= req
->req_offset
;
497 mme
->mme_size
= req
->req_size
;
500 mr
= mach_right_get(mp
, l
, MACH_PORT_TYPE_SEND
, 0);
502 *msglen
= sizeof(*rep
);
503 mach_set_header(rep
, req
, *msglen
);
504 mach_add_port_desc(rep
, mr
->mr_name
);
506 rep
->rep_size
= req
->req_size
;
508 mach_set_trailer(rep
, *msglen
);
514 mach_vm_region(struct mach_trap_args
*args
)
516 mach_vm_region_request_t
*req
= args
->smsg
;
517 mach_vm_region_reply_t
*rep
= args
->rmsg
;
518 size_t *msglen
= args
->rsize
;
519 struct lwp
*tl
= args
->tl
;
520 struct mach_vm_region_basic_info
*rbi
;
522 struct vm_map_entry
*vme
;
525 /* Sanity check req_count */
526 if (req
->req_count
> 9)
527 return mach_msg_error(args
, EINVAL
);
530 * MACH_VM_REGION_BASIC_INFO is the only
531 * supported flavor in Darwin.
533 if (req
->req_flavor
!= MACH_VM_REGION_BASIC_INFO
)
534 return mach_msg_error(args
, EINVAL
);
535 if (req
->req_count
!= (sizeof(*rbi
) / sizeof(int))) /* This is 8 */
536 return mach_msg_error(args
, EINVAL
);
537 *msglen
= sizeof(*rep
) + ((req
->req_count
- 9) * sizeof(int));
539 map
= &tl
->l_proc
->p_vmspace
->vm_map
;
542 error
= uvm_map_lookup_entry(map
, req
->req_addr
, &vme
);
546 return mach_msg_error(args
, ENOMEM
);
548 mach_set_header(rep
, req
, *msglen
);
549 mach_add_port_desc(rep
, 0); /* XXX Why this null name */
551 rep
->rep_addr
= vme
->start
;
552 rep
->rep_size
= vme
->end
- vme
->start
;
553 rep
->rep_count
= req
->req_count
;
555 rbi
= (struct mach_vm_region_basic_info
*)&rep
->rep_info
[0];
556 rbi
->protection
= vme
->protection
;
557 rbi
->inheritance
= 1; /* vme->inheritance */
558 rbi
->shared
= 0; /* XXX how can we know? */
559 rbi
->offset
= vme
->offset
;
560 rbi
->behavior
= MACH_VM_BEHAVIOR_DEFAULT
; /* XXX What is it? */
561 rbi
->user_wired_count
= vme
->wired_count
;
564 *(short *)((u_long
)&rbi
->user_wired_count
+ sizeof(short)) = 1;
566 mach_set_trailer(rep
, *msglen
);
572 mach_vm_region_64(struct mach_trap_args
*args
)
574 mach_vm_region_64_request_t
*req
= args
->smsg
;
575 mach_vm_region_64_reply_t
*rep
= args
->rmsg
;
576 size_t *msglen
= args
->rsize
;
577 struct lwp
*tl
= args
->tl
;
578 struct mach_vm_region_basic_info_64
*rbi
;
580 struct vm_map_entry
*vme
;
583 /* Sanity check req_count */
584 if (req
->req_count
> 10)
585 return mach_msg_error(args
, EINVAL
);
588 * MACH_VM_REGION_BASIC_INFO is the only
589 * supported flavor in Darwin.
591 if (req
->req_flavor
!= MACH_VM_REGION_BASIC_INFO
)
592 return mach_msg_error(args
, EINVAL
);
593 if (req
->req_count
!= (sizeof(*rbi
) / sizeof(int))) /* This is 8 */
594 return mach_msg_error(args
, EINVAL
);
595 *msglen
= sizeof(*rep
) + ((req
->req_count
- 9) * sizeof(int));
597 map
= &tl
->l_proc
->p_vmspace
->vm_map
;
600 error
= uvm_map_lookup_entry(map
, req
->req_addr
, &vme
);
604 return mach_msg_error(args
, ENOMEM
);
606 mach_set_header(rep
, req
, *msglen
);
607 mach_add_port_desc(rep
, 0); /* XXX null port ? */
609 rep
->rep_size
= PAGE_SIZE
; /* XXX Why? */
610 rep
->rep_count
= req
->req_count
;
612 rbi
= (struct mach_vm_region_basic_info_64
*)&rep
->rep_info
[0];
613 rbi
->protection
= vme
->protection
;
614 rbi
->inheritance
= 1; /* vme->inheritance */
615 rbi
->shared
= 0; /* XXX how can we know? */
616 rbi
->offset
= vme
->offset
;
617 rbi
->behavior
= MACH_VM_BEHAVIOR_DEFAULT
; /* XXX What is it? */
618 rbi
->user_wired_count
= vme
->wired_count
;
621 *(short *)((u_long
)&rbi
->user_wired_count
+ sizeof(short)) = 1;
623 mach_set_trailer(rep
, *msglen
);
629 mach_vm_msync(struct mach_trap_args
*args
)
631 mach_vm_msync_request_t
*req
= args
->smsg
;
632 mach_vm_msync_reply_t
*rep
= args
->rmsg
;
633 size_t *msglen
= args
->rsize
;
634 struct lwp
*tl
= args
->tl
;
635 struct sys___msync13_args cup
;
639 SCARG(&cup
, addr
) = (void *)req
->req_addr
;
640 SCARG(&cup
, len
) = req
->req_size
;
641 SCARG(&cup
, flags
) = 0;
642 if (req
->req_flags
& MACH_VM_SYNC_ASYNCHRONOUS
)
643 SCARG(&cup
, flags
) |= MS_ASYNC
;
644 if (req
->req_flags
& MACH_VM_SYNC_SYNCHRONOUS
)
645 SCARG(&cup
, flags
) |= MS_SYNC
;
646 if (req
->req_flags
& MACH_VM_SYNC_INVALIDATE
)
647 SCARG(&cup
, flags
) |= MS_INVALIDATE
;
649 error
= sys___msync13(tl
, &cup
, &dontcare
);
651 *msglen
= sizeof(*rep
);
652 mach_set_header(rep
, req
, *msglen
);
654 rep
->rep_retval
= native_to_mach_errno
[error
];
656 mach_set_trailer(rep
, *msglen
);
661 /* XXX Do it for remote task */
663 mach_vm_copy(struct mach_trap_args
*args
)
665 mach_vm_copy_request_t
*req
= args
->smsg
;
666 mach_vm_copy_reply_t
*rep
= args
->rmsg
;
667 size_t *msglen
= args
->rsize
;
674 printf("mach_vm_copy: src = 0x%08lx, size = 0x%08lx, addr = 0x%08lx\n",
675 (long)req
->req_src
, (long)req
->req_size
, (long)req
->req_addr
);
677 if ((req
->req_src
& (PAGE_SIZE
- 1)) ||
678 (req
->req_addr
& (PAGE_SIZE
- 1)) ||
679 (req
->req_size
& (PAGE_SIZE
- 1)))
680 return mach_msg_error(args
, EINVAL
);
682 src
= (void *)req
->req_src
;
683 dst
= (void *)req
->req_addr
;
684 size
= (size_t)req
->req_size
;
686 tmpbuf
= malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
688 /* Is there an easy way of dealing with that efficiently? */
690 if ((error
= copyin(src
, tmpbuf
, PAGE_SIZE
)) != 0)
693 if ((error
= copyout(tmpbuf
, dst
, PAGE_SIZE
)) != 0)
701 *msglen
= sizeof(*rep
);
702 mach_set_header(rep
, req
, *msglen
);
706 mach_set_trailer(rep
, *msglen
);
708 free(tmpbuf
, M_TEMP
);
712 free(tmpbuf
, M_TEMP
);
713 return mach_msg_error(args
, error
);
717 mach_vm_read(struct mach_trap_args
*args
)
719 mach_vm_read_request_t
*req
= args
->smsg
;
720 mach_vm_read_reply_t
*rep
= args
->rmsg
;
721 size_t *msglen
= args
->rsize
;
722 struct lwp
*l
= args
->l
;
723 struct lwp
*tl
= args
->tl
;
730 size
= req
->req_size
;
731 va
= vm_map_min(&l
->l_proc
->p_vmspace
->vm_map
);
732 if ((error
= uvm_map(&l
->l_proc
->p_vmspace
->vm_map
, &va
,
733 round_page(size
), NULL
, UVM_UNKNOWN_OFFSET
, 0,
734 UVM_MAPFLAG(UVM_PROT_RW
, UVM_PROT_ALL
,
735 UVM_INH_COPY
, UVM_ADV_NORMAL
, UVM_FLAG_COPYONW
))) != 0) {
736 printf("uvm_map error = %d\n", error
);
737 return mach_msg_error(args
, EFAULT
);
741 * Copy the data from the target process to the current process
742 * This is reasonable for small chunk of data, but we should
743 * remap COW for areas bigger than a page.
745 tbuf
= malloc(size
, M_EMULDATA
, M_WAITOK
);
747 addr
= (void *)req
->req_addr
;
748 if ((error
= copyin_proc(tl
->l_proc
, addr
, tbuf
, size
)) != 0) {
749 printf("copyin_proc error = %d, addr = %p, size = %x\n", error
, addr
, size
);
750 free(tbuf
, M_WAITOK
);
751 return mach_msg_error(args
, EFAULT
);
754 if ((error
= copyout(tbuf
, (void *)va
, size
)) != 0) {
755 printf("copyout error = %d\n", error
);
756 free(tbuf
, M_WAITOK
);
757 return mach_msg_error(args
, EFAULT
);
761 ktrmool(tbuf
, size
, (void *)va
);
763 free(tbuf
, M_WAITOK
);
765 *msglen
= sizeof(*rep
);
766 mach_set_header(rep
, req
, *msglen
);
767 mach_add_ool_desc(rep
, (void *)va
, size
);
769 rep
->rep_count
= size
;
771 mach_set_trailer(rep
, *msglen
);
777 mach_vm_write(struct mach_trap_args
*args
)
779 mach_vm_write_request_t
*req
= args
->smsg
;
780 mach_vm_write_reply_t
*rep
= args
->rmsg
;
781 size_t *msglen
= args
->rsize
;
782 struct lwp
*tl
= args
->tl
;
789 if (req
->req_body
.msgh_descriptor_count
!= 1)
790 printf("mach_vm_write: OOL descriptor count is not 1\n");
794 * Copy the data from the current process to the target process
795 * This is reasonable for small chunk of data, but we should
796 * remap COW for areas bigger than a page.
798 size
= req
->req_data
.size
;
799 tbuf
= malloc(size
, M_EMULDATA
, M_WAITOK
);
801 if ((error
= copyin(req
->req_data
.address
, tbuf
, size
)) != 0) {
802 printf("copyin error = %d\n", error
);
803 free(tbuf
, M_WAITOK
);
804 return mach_msg_error(args
, EFAULT
);
807 addr
= (void *)req
->req_addr
;
808 if ((error
= copyout_proc(tl
->l_proc
, tbuf
, addr
, size
)) != 0) {
809 printf("copyout_proc error = %d\n", error
);
810 free(tbuf
, M_WAITOK
);
811 return mach_msg_error(args
, EFAULT
);
815 ktrmool(tbuf
, size
, (void *)addr
);
817 free(tbuf
, M_WAITOK
);
819 *msglen
= sizeof(*rep
);
820 mach_set_header(rep
, req
, *msglen
);
824 mach_set_trailer(rep
, *msglen
);
830 mach_vm_machine_attribute(struct mach_trap_args
*args
)
832 mach_vm_machine_attribute_request_t
*req
= args
->smsg
;
833 mach_vm_machine_attribute_reply_t
*rep
= args
->rmsg
;
834 size_t *msglen
= args
->rsize
;
835 struct lwp
*tl
= args
->tl
;
837 int attribute
, value
;
839 attribute
= req
->req_attribute
;
840 value
= req
->req_value
;
843 case MACH_MATTR_CACHE
:
845 case MACH_MATTR_VAL_CACHE_FLUSH
:
846 case MACH_MATTR_VAL_DCACHE_FLUSH
:
847 case MACH_MATTR_VAL_ICACHE_FLUSH
:
848 case MACH_MATTR_VAL_CACHE_SYNC
:
849 error
= mach_vm_machine_attribute_machdep(tl
,
850 req
->req_addr
, req
->req_size
, &value
);
854 printf("unimplemented value %d\n", req
->req_value
);
861 case MACH_MATTR_MIGRATE
:
862 case MACH_MATTR_REPLICATE
:
865 printf("unimplemented attribute %d\n", req
->req_attribute
);
871 *msglen
= sizeof(*rep
);
872 mach_set_header(rep
, req
, *msglen
);
874 rep
->rep_retval
= native_to_mach_errno
[error
];
876 rep
->rep_value
= value
;
878 mach_set_trailer(rep
, *msglen
);