The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/mach/mach_vm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: mach_vm.c,v 1.60 2008/04/28 20:23:45 martin Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002-2003, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   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.
   18  *
   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.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: mach_vm.c,v 1.60 2008/04/28 20:23:45 martin Exp $");
   34 
   35 #include <sys/types.h>
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/mount.h>
   39 #include <sys/proc.h>
   40 #include <sys/mman.h>
   41 #include <sys/malloc.h>
   42 #include <sys/vnode.h>
   43 #include <sys/file.h>
   44 #include <sys/filedesc.h>
   45 #include <sys/ktrace.h>
   46 #include <sys/exec.h>
   47 #include <sys/syscallargs.h>
   48 
   49 #include <uvm/uvm_prot.h>
   50 #include <uvm/uvm_map.h>
   51 #include <uvm/uvm_extern.h>
   52 
   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>
   61 
   62 int
   63 mach_vm_map(struct mach_trap_args *args)
   64 {
   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;
   71         vaddr_t addr;
   72         int error, flags;
   73         void *ret;
   74 
   75 #ifdef DEBUG_MACH_VM
   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,
   82             req->req_inherance);
   83 #endif
   84 
   85         /* XXX Darwin fails on mapping a page at address 0 */
   86         if (req->req_address == 0)
   87                 return mach_msg_error(args, ENOMEM);
   88 
   89         req->req_size = round_page(req->req_size);
   90 
   91         /* Where Mach uses 0x00ff, we use 0x0100 */
   92         if ((req->req_mask & (req->req_mask + 1)) || (req->req_mask == 0))
   93                 req->req_mask = 0;
   94         else
   95                 req->req_mask += 1;
   96 
   97         if (req->req_flags & MACH_VM_FLAGS_ANYWHERE) {
   98                 SCARG(&cup, flags) = MAP_ANON;
   99                 flags = 0;
  100         } else {
  101                 SCARG(&cup, flags) = MAP_ANON | MAP_FIXED;
  102                 flags = MAP_FIXED;
  103         }
  104 
  105         /*
  106          * Use uvm_map_findspace to find a place which conforms to the
  107          * requested alignement.
  108          */
  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);
  114 
  115         if (ret == NULL)
  116                 return mach_msg_error(args, ENOMEM);
  117 
  118         switch(req->req_inherance) {
  119         case MACH_VM_INHERIT_SHARE:
  120                 SCARG(&cup, flags) |= MAP_INHERIT;
  121                 break;
  122         case MACH_VM_INHERIT_COPY:
  123                 SCARG(&cup, flags) |= MAP_COPY;
  124                 break;
  125         case MACH_VM_INHERIT_NONE:
  126                 break;
  127         case MACH_VM_INHERIT_DONATE_COPY:
  128         default:
  129                 uprintf("mach_vm_map: unsupported inherance flag %d\n",
  130                     req->req_inherance);
  131                 break;
  132         }
  133 
  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;
  139 
  140         if ((error = sys_mmap(tl, &cup, &rep->rep_retval)) != 0)
  141                 return mach_msg_error(args, error);
  142 
  143         *msglen = sizeof(*rep);
  144         mach_set_header(rep, req, *msglen);
  145         mach_set_trailer(rep, *msglen);
  146 
  147         return 0;
  148 }
  149 
  150 int
  151 mach_vm_allocate(struct mach_trap_args *args)
  152 {
  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;
  159         vaddr_t addr;
  160         size_t size;
  161         int error;
  162 
  163         addr = req->req_address;
  164         size = req->req_size;
  165 
  166 #ifdef DEBUG_MACH_VM
  167         printf("mach_vm_allocate(addr = %p, size = 0x%08x);\n",
  168             (void *)addr, size);
  169 #endif
  170 
  171         /*
  172          * Avoid mappings at address zero: it should
  173          * be a "red zone" with nothing mapped on it.
  174          */
  175         if (addr == 0) {
  176                 if (req->req_flags & MACH_VM_FLAGS_ANYWHERE)
  177                         addr = 0x1000;
  178                 else
  179                         return mach_msg_error(args, EINVAL);
  180 #ifdef DEBUG_MACH_VM
  181                 printf("mach_vm_allocate: trying addr = %p\n", (void *)addr);
  182 #endif
  183         }
  184 
  185         size = round_page(size);
  186         if (req->req_flags & MACH_VM_FLAGS_ANYWHERE)
  187                 addr = vm_map_min(&tp->p_vmspace->vm_map);
  188         else
  189                 addr = trunc_page(addr);
  190 
  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);
  194 
  195         if (size == 0)
  196                 goto out;
  197 
  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;
  206 
  207         if ((error = sys_mmap(tl, &cup, &rep->rep_address)) != 0)
  208                 return mach_msg_error(args, error);
  209 #ifdef DEBUG_MACH_VM
  210         printf("vm_allocate: success at %p\n", (void *)rep->rep_address);
  211 #endif
  212 
  213 out:
  214         *msglen = sizeof(*rep);
  215         mach_set_header(rep, req, *msglen);
  216 
  217         rep->rep_retval = 0;
  218 
  219         mach_set_trailer(rep, *msglen);
  220 
  221         return 0;
  222 }
  223 
  224 int
  225 mach_vm_deallocate(struct mach_trap_args *args)
  226 {
  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;
  232         int error;
  233 
  234 #ifdef DEBUG_MACH_VM
  235         printf("mach_vm_deallocate(addr = %p, size = 0x%08lx);\n",
  236             (void *)req->req_address, (long)req->req_size);
  237 #endif
  238 
  239         SCARG(&cup, addr) = (void *)req->req_address;
  240         SCARG(&cup, len) = req->req_size;
  241 
  242         if ((error = sys_munmap(tl, &cup, &rep->rep_retval)) != 0)
  243                 return mach_msg_error(args, error);
  244 
  245         *msglen = sizeof(*rep);
  246         mach_set_header(rep, req, *msglen);
  247         mach_set_trailer(rep, *msglen);
  248 
  249         return 0;
  250 }
  251 
  252 /*
  253  * XXX This server message Id clashes with bootstrap_look_up.
  254  * Is there a way to resolve this easily?
  255  */
  256 #if 0
  257 int
  258 mach_vm_wire(struct mach_trap_args *args)
  259 {
  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;
  264         register_t retval;
  265         int error;
  266 
  267 #ifdef DEBUG_MACH_VM
  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);
  270 #endif
  271 
  272         bzero(&rep, sizeof(*rep));
  273 
  274         if ((req->req_access & ~VM_PROT_ALL) != 0)
  275                 return mach_msg_error(args, EINVAL);
  276 
  277         /*
  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.
  280          */
  281         if (req->req_access == 0) {
  282                 struct sys_munlock_args cup;
  283 
  284                 SCARG(&cup, addr) = (void *)req->req_address;
  285                 SCARG(&cup, len) = req->req_size;
  286                 error = sys_munlock(tl, &cup, &retval);
  287         } else {
  288                 struct sys_mlock_args cup;
  289 
  290                 SCARG(&cup, addr) = (void *)req->req_address;
  291                 SCARG(&cup, len) = req->req_size;
  292                 error = sys_mlock(tl, &cup, &retval);
  293         }
  294         if (error != 0)
  295                 return mach_msg_error(args, error);
  296 
  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);
  301 
  302         *msglen = sizeof(*rep);
  303         mach_set_header(rep, req, *msglen);
  304         mach_set_trailer(rep, *msglen);
  305 
  306         return 0;
  307 }
  308 #endif
  309 
  310 int
  311 mach_vm_protect(struct mach_trap_args *args)
  312 {
  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;
  318         register_t retval;
  319         int error;
  320 
  321         SCARG(&cup, addr) = (void *)req->req_addr;
  322         SCARG(&cup, len) = req->req_size;
  323         SCARG(&cup, prot) = req->req_prot;
  324 
  325         if ((error = sys_mprotect(tl, &cup, &retval)) != 0)
  326                 return mach_msg_error(args, error);
  327 
  328         *msglen = sizeof(*rep);
  329         mach_set_header(rep, req, *msglen);
  330         mach_set_trailer(rep, *msglen);
  331 
  332         return 0;
  333 }
  334 
  335 int
  336 mach_sys_map_fd(struct lwp *l, const struct mach_sys_map_fd_args *uap, register_t *retval)
  337 {
  338         /* {
  339                 syscallarg(int) fd;
  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;
  344         } */
  345         file_t *fp;
  346         struct vnode *vp;
  347         struct exec_vmcmd evc;
  348         struct vm_map_entry *ret;
  349         struct proc *p = l->l_proc;
  350         register_t dontcare;
  351         struct sys_munmap_args cup;
  352         void *va;
  353         int error;
  354 
  355         if ((error = copyin(SCARG(uap, va), (void *)&va, sizeof(va))) != 0)
  356                 return error;
  357 
  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);
  363         }
  364 
  365         fp = fd_getfile(SCARG(uap, fd));
  366         if (fp == NULL)
  367                 return EBADF;
  368 
  369         vp = fp->f_data;
  370         vref(vp);
  371 
  372 #ifdef DEBUG_MACH_VM
  373         printf("vm_map_fd: addr = %p len = 0x%08lx\n",
  374             va, (long)SCARG(uap, size));
  375 #endif
  376         bzero(&evc, 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);
  383         evc.ev_vp = vp;
  384 
  385         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  386         if ((error = (*evc.ev_proc)(l, &evc)) != 0) {
  387                 VOP_UNLOCK(vp, 0);
  388 
  389 #ifdef DEBUG_MACH_VM
  390                 printf("mach_sys_map_fd: mapping at %p failed\n", va);
  391 #endif
  392 
  393                 if (SCARG(uap, findspace) == 0)
  394                         goto bad2;
  395 
  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);
  401                         goto bad2;
  402                 }
  403                 vm_map_unlock(&p->p_vmspace->vm_map);
  404 
  405                 va = (void *)evc.ev_addr;
  406 
  407                 bzero(&evc, sizeof(evc));
  408                 evc.ev_addr = (u_long)va;
  409                 evc.ev_len = SCARG(uap, size);
  410                 evc.ev_prot = VM_PROT_ALL;
  411                 evc.ev_flags = 0;
  412                 evc.ev_proc = vmcmd_map_readvn;
  413                 evc.ev_offset = SCARG(uap, offset);
  414                 evc.ev_vp = vp;
  415 
  416 #ifdef DEBUG_MACH_VM
  417                 printf("mach_sys_map_fd: trying at %p\n", va);
  418 #endif
  419                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  420                 if ((error = (*evc.ev_proc)(l, &evc)) != 0)
  421                         goto bad1;
  422         }
  423 
  424         vput(vp);
  425         fd_putfile(SCARG(uap, fd));
  426 #ifdef DEBUG_MACH_VM
  427         printf("mach_sys_map_fd: mapping at %p\n", (void *)evc.ev_addr);
  428 #endif
  429 
  430         va = (mach_vm_offset_t *)evc.ev_addr;
  431 
  432         if ((error = copyout((void *)&va, SCARG(uap, va), sizeof(va))) != 0)
  433                 return error;
  434 
  435         return 0;
  436 
  437 bad1:
  438         VOP_UNLOCK(vp, 0);
  439 bad2:
  440         vrele(vp);
  441         fd_putfile(SCARG(uap, fd));
  442 #ifdef DEBUG_MACH_VM
  443         printf("mach_sys_map_fd: mapping at %p failed, error = %d\n",
  444             (void *)evc.ev_addr, error);
  445 #endif
  446         return error;
  447 }
  448 
  449 int
  450 mach_vm_inherit(struct mach_trap_args *args)
  451 {
  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;
  457         register_t retval;
  458         int error;
  459 
  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;
  464 
  465         if ((error = sys_minherit(tl, &cup, &retval)) != 0)
  466                 return mach_msg_error(args, error);
  467 
  468         *msglen = sizeof(*rep);
  469         mach_set_header(rep, req, *msglen);
  470         mach_set_trailer(rep, *msglen);
  471 
  472         return 0;
  473 }
  474 
  475 int
  476 mach_make_memory_entry_64(struct mach_trap_args *args)
  477 {
  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;
  486 
  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);
  489 
  490         mp = mach_port_get();
  491         mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
  492         mp->mp_datatype = MACH_MP_MEMORY_ENTRY;
  493 
  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;
  498         mp->mp_data = mme;
  499 
  500         mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
  501 
  502         *msglen = sizeof(*rep);
  503         mach_set_header(rep, req, *msglen);
  504         mach_add_port_desc(rep, mr->mr_name);
  505 
  506         rep->rep_size = req->req_size;
  507 
  508         mach_set_trailer(rep, *msglen);
  509 
  510         return 0;
  511 }
  512 
  513 int
  514 mach_vm_region(struct mach_trap_args *args)
  515 {
  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;
  521         struct vm_map *map;
  522         struct vm_map_entry *vme;
  523         int error;
  524 
  525         /* Sanity check req_count */
  526         if (req->req_count > 9)
  527                 return mach_msg_error(args, EINVAL);
  528 
  529         /*
  530          * MACH_VM_REGION_BASIC_INFO is the only
  531          * supported flavor in Darwin.
  532          */
  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));
  538 
  539         map = &tl->l_proc->p_vmspace->vm_map;
  540 
  541         vm_map_lock(map);
  542         error = uvm_map_lookup_entry(map, req->req_addr, &vme);
  543         vm_map_unlock(map);
  544 
  545         if (error == 0)
  546                 return mach_msg_error(args, ENOMEM);
  547 
  548         mach_set_header(rep, req, *msglen);
  549         mach_add_port_desc(rep, 0); /* XXX Why this null name */
  550 
  551         rep->rep_addr = vme->start;
  552         rep->rep_size = vme->end - vme->start;
  553         rep->rep_count = req->req_count;
  554 
  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;
  562 
  563         /* XXX Why this? */
  564         *(short *)((u_long)&rbi->user_wired_count + sizeof(short)) = 1;
  565 
  566         mach_set_trailer(rep, *msglen);
  567 
  568         return 0;
  569 }
  570 
  571 int
  572 mach_vm_region_64(struct mach_trap_args *args)
  573 {
  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;
  579         struct vm_map *map;
  580         struct vm_map_entry *vme;
  581         int error;
  582 
  583         /* Sanity check req_count */
  584         if (req->req_count > 10)
  585                 return mach_msg_error(args, EINVAL);
  586 
  587         /*
  588          * MACH_VM_REGION_BASIC_INFO is the only
  589          * supported flavor in Darwin.
  590          */
  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));
  596 
  597         map = &tl->l_proc->p_vmspace->vm_map;
  598 
  599         vm_map_lock(map);
  600         error = uvm_map_lookup_entry(map, req->req_addr, &vme);
  601         vm_map_unlock(map);
  602 
  603         if (error == 0)
  604                 return mach_msg_error(args, ENOMEM);
  605 
  606         mach_set_header(rep, req, *msglen);
  607         mach_add_port_desc(rep, 0);     /* XXX null port ? */
  608 
  609         rep->rep_size = PAGE_SIZE; /* XXX Why? */
  610         rep->rep_count = req->req_count;
  611 
  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;
  619 
  620         /* XXX Why this? */
  621         *(short *)((u_long)&rbi->user_wired_count + sizeof(short)) = 1;
  622 
  623         mach_set_trailer(rep, *msglen);
  624 
  625         return 0;
  626 }
  627 
  628 int
  629 mach_vm_msync(struct mach_trap_args *args)
  630 {
  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;
  636         int error;
  637         register_t dontcare;
  638 
  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;
  648 
  649         error = sys___msync13(tl, &cup, &dontcare);
  650 
  651         *msglen = sizeof(*rep);
  652         mach_set_header(rep, req, *msglen);
  653 
  654         rep->rep_retval = native_to_mach_errno[error];
  655 
  656         mach_set_trailer(rep, *msglen);
  657 
  658         return 0;
  659 }
  660 
  661 /* XXX Do it for remote task */
  662 int
  663 mach_vm_copy(struct mach_trap_args *args)
  664 {
  665         mach_vm_copy_request_t *req = args->smsg;
  666         mach_vm_copy_reply_t *rep = args->rmsg;
  667         size_t *msglen = args->rsize;
  668         char *tmpbuf;
  669         int error;
  670         char *src, *dst;
  671         size_t size;
  672 
  673 #ifdef DEBUG_MACH_VM
  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);
  676 #endif
  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);
  681 
  682         src = (void *)req->req_src;
  683         dst = (void *)req->req_addr;
  684         size = (size_t)req->req_size;
  685 
  686         tmpbuf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  687 
  688         /* Is there an easy way of dealing with that efficiently? */
  689         do {
  690                 if ((error = copyin(src, tmpbuf, PAGE_SIZE)) != 0)
  691                         goto out;
  692 
  693                 if ((error = copyout(tmpbuf, dst, PAGE_SIZE)) != 0)
  694                         goto out;
  695 
  696                 src += PAGE_SIZE;
  697                 dst += PAGE_SIZE;
  698                 size -= PAGE_SIZE;
  699         } while (size > 0);
  700 
  701         *msglen = sizeof(*rep);
  702         mach_set_header(rep, req, *msglen);
  703 
  704         rep->rep_retval = 0;
  705 
  706         mach_set_trailer(rep, *msglen);
  707 
  708         free(tmpbuf, M_TEMP);
  709         return 0;
  710 
  711 out:
  712         free(tmpbuf, M_TEMP);
  713         return mach_msg_error(args, error);
  714 }
  715 
  716 int
  717 mach_vm_read(struct mach_trap_args *args)
  718 {
  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;
  724         char *tbuf;
  725         void *addr;
  726         vaddr_t va;
  727         size_t size;
  728         int error;
  729 
  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);
  738         }
  739 
  740         /*
  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.
  744          */
  745         tbuf = malloc(size, M_EMULDATA, M_WAITOK);
  746 
  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);
  752         }
  753 
  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);
  758         }
  759 
  760         if (error == 0)
  761                 ktrmool(tbuf, size, (void *)va);
  762 
  763         free(tbuf, M_WAITOK);
  764 
  765         *msglen = sizeof(*rep);
  766         mach_set_header(rep, req, *msglen);
  767         mach_add_ool_desc(rep, (void *)va, size);
  768 
  769         rep->rep_count = size;
  770 
  771         mach_set_trailer(rep, *msglen);
  772 
  773         return 0;
  774 }
  775 
  776 int
  777 mach_vm_write(struct mach_trap_args *args)
  778 {
  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;
  783         size_t size;
  784         void *addr;
  785         char *tbuf;
  786         int error;
  787 
  788 #ifdef DEBUG_MACH
  789         if (req->req_body.msgh_descriptor_count != 1)
  790                 printf("mach_vm_write: OOL descriptor count is not 1\n");
  791 #endif
  792 
  793         /*
  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.
  797          */
  798         size = req->req_data.size;
  799         tbuf = malloc(size, M_EMULDATA, M_WAITOK);
  800 
  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);
  805         }
  806 
  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);
  812         }
  813 
  814         if (error == 0)
  815                 ktrmool(tbuf, size, (void *)addr);
  816 
  817         free(tbuf, M_WAITOK);
  818 
  819         *msglen = sizeof(*rep);
  820         mach_set_header(rep, req, *msglen);
  821 
  822         rep->rep_retval = 0;
  823 
  824         mach_set_trailer(rep, *msglen);
  825 
  826         return 0;
  827 }
  828 
  829 int
  830 mach_vm_machine_attribute(struct mach_trap_args *args)
  831 {
  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;
  836         int error = 0;
  837         int attribute, value;
  838 
  839         attribute = req->req_attribute;
  840         value = req->req_value;
  841 
  842         switch (attribute) {
  843         case MACH_MATTR_CACHE:
  844                 switch(value) {
  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);
  851                         break;
  852                 default:
  853 #ifdef DEBUG_MACH
  854                         printf("unimplemented value %d\n", req->req_value);
  855 #endif
  856                         error = EINVAL;
  857                         break;
  858                 }
  859                 break;
  860 
  861         case MACH_MATTR_MIGRATE:
  862         case MACH_MATTR_REPLICATE:
  863         default:
  864 #ifdef DEBUG_MACH
  865                 printf("unimplemented attribute %d\n", req->req_attribute);
  866 #endif
  867                 error = EINVAL;
  868                 break;
  869         }
  870 
  871         *msglen = sizeof(*rep);
  872         mach_set_header(rep, req, *msglen);
  873 
  874         rep->rep_retval = native_to_mach_errno[error];
  875         if (error != 0)
  876                 rep->rep_value = value;
  877 
  878         mach_set_trailer(rep, *msglen);
  879 
  880         return 0;
  881 }

Cache object: 97f31278f914923512eb25f214e9ef01


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.