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.53 2006/11/16 01:32:44 christos Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002-2003 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  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include "opt_ktrace.h"
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: mach_vm.c,v 1.53 2006/11/16 01:32:44 christos Exp $");
   43 
   44 #include <sys/types.h>
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/mount.h>
   48 #include <sys/proc.h>
   49 #include <sys/sa.h>
   50 #include <sys/mman.h>
   51 #include <sys/malloc.h>
   52 #include <sys/vnode.h>
   53 #include <sys/file.h>
   54 #include <sys/filedesc.h>
   55 #include <sys/ktrace.h>
   56 #include <sys/exec.h>
   57 #include <sys/syscallargs.h>
   58 
   59 #include <uvm/uvm_prot.h>
   60 #include <uvm/uvm_map.h>
   61 #include <uvm/uvm_extern.h>
   62 
   63 #include <compat/mach/mach_types.h>
   64 #include <compat/mach/mach_message.h>
   65 #include <compat/mach/mach_clock.h>
   66 #include <compat/mach/mach_vm.h>
   67 #include <compat/mach/mach_errno.h>
   68 #include <compat/mach/mach_port.h>
   69 #include <compat/mach/mach_services.h>
   70 #include <compat/mach/mach_syscallargs.h>
   71 
   72 int
   73 mach_vm_map(args)
   74         struct mach_trap_args *args;
   75 {
   76         mach_vm_map_request_t *req = args->smsg;
   77         mach_vm_map_reply_t *rep = args->rmsg;
   78         size_t *msglen = args->rsize;
   79         struct lwp *tl = args->tl;
   80         struct proc *tp = tl->l_proc;
   81         struct sys_mmap_args cup;
   82         vaddr_t addr;
   83         int error, flags;
   84         void *ret;
   85 
   86 #ifdef DEBUG_MACH_VM
   87         printf("mach_vm_map(addr = %p, size = 0x%08lx, obj = 0x%x, "
   88             "mask = 0x%08lx, flags = 0x%x, offset = 0x%08llx, "
   89             "copy = %d, cur_prot = 0x%x, max_prot = 0x%x, inh = 0x%x);\n",
   90             (void *)req->req_address, (long)req->req_size, req->req_object.name,
   91             (long)req->req_mask, req->req_flags, (off_t)req->req_offset,
   92             req->req_copy, req->req_cur_protection, req->req_max_protection,
   93             req->req_inherance);
   94 #endif
   95 
   96         /* XXX Darwin fails on mapping a page at address 0 */
   97         if (req->req_address == 0)
   98                 return mach_msg_error(args, ENOMEM);
   99 
  100         req->req_size = round_page(req->req_size);
  101 
  102         /* Where Mach uses 0x00ff, we use 0x0100 */
  103         if ((req->req_mask & (req->req_mask + 1)) || (req->req_mask == 0))
  104                 req->req_mask = 0;
  105         else
  106                 req->req_mask += 1;
  107 
  108         if (req->req_flags & MACH_VM_FLAGS_ANYWHERE) {
  109                 SCARG(&cup, flags) = MAP_ANON;
  110                 flags = 0;
  111         } else {
  112                 SCARG(&cup, flags) = MAP_ANON | MAP_FIXED;
  113                 flags = MAP_FIXED;
  114         }
  115 
  116         /*
  117          * Use uvm_map_findspace to find a place which conforms to the
  118          * requested alignement.
  119          */
  120         vm_map_lock(&tp->p_vmspace->vm_map);
  121         ret = uvm_map_findspace(&tp->p_vmspace->vm_map,
  122             trunc_page(req->req_address), req->req_size, &addr,
  123             NULL, 0, req->req_mask, flags);
  124         vm_map_unlock(&tp->p_vmspace->vm_map);
  125 
  126         if (ret == NULL)
  127                 return mach_msg_error(args, ENOMEM);
  128 
  129         switch(req->req_inherance) {
  130         case MACH_VM_INHERIT_SHARE:
  131                 SCARG(&cup, flags) |= MAP_INHERIT;
  132                 break;
  133         case MACH_VM_INHERIT_COPY:
  134                 SCARG(&cup, flags) |= MAP_COPY;
  135                 break;
  136         case MACH_VM_INHERIT_NONE:
  137                 break;
  138         case MACH_VM_INHERIT_DONATE_COPY:
  139         default:
  140                 uprintf("mach_vm_map: unsupported inherance flag %d\n",
  141                     req->req_inherance);
  142                 break;
  143         }
  144 
  145         SCARG(&cup, addr) = (void *)addr;
  146         SCARG(&cup, len) = req->req_size;
  147         SCARG(&cup, prot) = req->req_cur_protection;
  148         SCARG(&cup, fd) = -1;           /* XXX For now, no object mapping */
  149         SCARG(&cup, pos) = req->req_offset;
  150 
  151         if ((error = sys_mmap(tl, &cup, &rep->rep_retval)) != 0)
  152                 return mach_msg_error(args, error);
  153 
  154         *msglen = sizeof(*rep);
  155         mach_set_header(rep, req, *msglen);
  156         mach_set_trailer(rep, *msglen);
  157 
  158         return 0;
  159 }
  160 
  161 int
  162 mach_vm_allocate(args)
  163         struct mach_trap_args *args;
  164 {
  165         mach_vm_allocate_request_t *req = args->smsg;
  166         mach_vm_allocate_reply_t *rep = args->rmsg;
  167         size_t *msglen = args->rsize;
  168         struct lwp *tl = args->tl;
  169         struct proc *tp = tl->l_proc;
  170         struct sys_mmap_args cup;
  171         vaddr_t addr;
  172         size_t size;
  173         int error;
  174 
  175         addr = req->req_address;
  176         size = req->req_size;
  177 
  178 #ifdef DEBUG_MACH_VM
  179         printf("mach_vm_allocate(addr = %p, size = 0x%08x);\n",
  180             (void *)addr, size);
  181 #endif
  182 
  183         /*
  184          * Avoid mappings at address zero: it should
  185          * be a "red zone" with nothing mapped on it.
  186          */
  187         if (addr == 0) {
  188                 if (req->req_flags & MACH_VM_FLAGS_ANYWHERE)
  189                         addr = 0x1000;
  190                 else
  191                         return mach_msg_error(args, EINVAL);
  192 #ifdef DEBUG_MACH_VM
  193                 printf("mach_vm_allocate: trying addr = %p\n", (void *)addr);
  194 #endif
  195         }
  196 
  197         size = round_page(size);
  198         if (req->req_flags & MACH_VM_FLAGS_ANYWHERE)
  199                 addr = vm_map_min(&tp->p_vmspace->vm_map);
  200         else
  201                 addr = trunc_page(addr);
  202 
  203         if (((addr + size) > vm_map_max(&tp->p_vmspace->vm_map)) ||
  204             ((addr + size) <= addr))
  205                 addr = vm_map_min(&tp->p_vmspace->vm_map);
  206 
  207         if (size == 0)
  208                 goto out;
  209 
  210         SCARG(&cup, addr) = (caddr_t)addr;
  211         SCARG(&cup, len) = size;
  212         SCARG(&cup, prot) = PROT_READ | PROT_WRITE;
  213         SCARG(&cup, flags) = MAP_ANON;
  214         if ((req->req_flags & MACH_VM_FLAGS_ANYWHERE) == 0)
  215                 SCARG(&cup, flags) |= MAP_FIXED;
  216         SCARG(&cup, fd) = -1;
  217         SCARG(&cup, pos) = 0;
  218 
  219         if ((error = sys_mmap(tl, &cup, &rep->rep_address)) != 0)
  220                 return mach_msg_error(args, error);
  221 #ifdef DEBUG_MACH_VM
  222         printf("vm_allocate: success at %p\n", (void *)rep->rep_address);
  223 #endif
  224 
  225 out:
  226         *msglen = sizeof(*rep);
  227         mach_set_header(rep, req, *msglen);
  228 
  229         rep->rep_retval = 0;
  230 
  231         mach_set_trailer(rep, *msglen);
  232 
  233         return 0;
  234 }
  235 
  236 int
  237 mach_vm_deallocate(args)
  238         struct mach_trap_args *args;
  239 {
  240         mach_vm_deallocate_request_t *req = args->smsg;
  241         mach_vm_deallocate_reply_t *rep = args->rmsg;
  242         size_t *msglen = args->rsize;
  243         struct lwp *tl = args->tl;
  244         struct sys_munmap_args cup;
  245         int error;
  246 
  247 #ifdef DEBUG_MACH_VM
  248         printf("mach_vm_deallocate(addr = %p, size = 0x%08lx);\n",
  249             (void *)req->req_address, (long)req->req_size);
  250 #endif
  251 
  252         SCARG(&cup, addr) = (caddr_t)req->req_address;
  253         SCARG(&cup, len) = req->req_size;
  254 
  255         if ((error = sys_munmap(tl, &cup, &rep->rep_retval)) != 0)
  256                 return mach_msg_error(args, error);
  257 
  258         *msglen = sizeof(*rep);
  259         mach_set_header(rep, req, *msglen);
  260         mach_set_trailer(rep, *msglen);
  261 
  262         return 0;
  263 }
  264 
  265 /*
  266  * XXX This server message Id clashes with bootstrap_look_up.
  267  * Is there a way to resolve this easily?
  268  */
  269 #if 0
  270 int
  271 mach_vm_wire(args)
  272         struct mach_trap_args *args;
  273 {
  274         mach_vm_wire_request_t *req = args->smsg;
  275         mach_vm_wire_reply_t *rep = args->rmsg;
  276         size_t *msglen = args->rsize;
  277         struct lwp *tl = args->tl;
  278         register_t retval;
  279         int error;
  280 
  281 #ifdef DEBUG_MACH_VM
  282         printf("mach_vm_wire(addr = %p, size = 0x%08x, prot = 0x%x);\n",
  283             (void *)req->req_address, req->req_size, req->req_access);
  284 #endif
  285 
  286         bzero(&rep, sizeof(*rep));
  287 
  288         if ((req->req_access & ~VM_PROT_ALL) != 0)
  289                 return mach_msg_error(args, EINVAL);
  290 
  291         /*
  292          * Mach maintains a count of how many times a page is wired
  293          * and unwire it once the count is zero. We cannot do that yet.
  294          */
  295         if (req->req_access == 0) {
  296                 struct sys_munlock_args cup;
  297 
  298                 SCARG(&cup, addr) = (void *)req->req_address;
  299                 SCARG(&cup, len) = req->req_size;
  300                 error = sys_munlock(tl, &cup, &retval);
  301         } else {
  302                 struct sys_mlock_args cup;
  303 
  304                 SCARG(&cup, addr) = (void *)req->req_address;
  305                 SCARG(&cup, len) = req->req_size;
  306                 error = sys_mlock(tl, &cup, &retval);
  307         }
  308         if (error != 0)
  309                 return mach_msg_error(args, error);
  310 
  311         if ((error = uvm_map_protect(&tl->l_proc->p_vmspace->vm_map,
  312             req->req_address, req->req_address + req->req_size,
  313             req->req_access, 0)) != 0)
  314                 return mach_msg_error(args, error);
  315 
  316         *msglen = sizeof(*rep);
  317         mach_set_header(rep, req, *msglen);
  318         mach_set_trailer(rep, *msglen);
  319 
  320         return 0;
  321 }
  322 #endif
  323 
  324 int
  325 mach_vm_protect(args)
  326         struct mach_trap_args *args;
  327 {
  328         mach_vm_protect_request_t *req = args->smsg;
  329         mach_vm_protect_reply_t *rep = args->rmsg;
  330         size_t *msglen = args->rsize;
  331         struct lwp *tl = args->tl;
  332         struct sys_mprotect_args cup;
  333         register_t retval;
  334         int error;
  335 
  336         SCARG(&cup, addr) = (void *)req->req_addr;
  337         SCARG(&cup, len) = req->req_size;
  338         SCARG(&cup, prot) = req->req_prot;
  339 
  340         if ((error = sys_mprotect(tl, &cup, &retval)) != 0)
  341                 return mach_msg_error(args, error);
  342 
  343         *msglen = sizeof(*rep);
  344         mach_set_header(rep, req, *msglen);
  345         mach_set_trailer(rep, *msglen);
  346 
  347         return 0;
  348 }
  349 
  350 int
  351 mach_sys_map_fd(struct lwp *l, void *v, register_t *retval)
  352 {
  353         struct mach_sys_map_fd_args /* {
  354                 syscallarg(int) fd;
  355                 syscallarg(mach_vm_offset_t) offset;
  356                 syscallarg(mach_vm_offset_t *) va;
  357                 syscallarg(mach_boolean_t) findspace;
  358                 syscallarg(mach_vm_size_t) size;
  359         } */ *uap = v;
  360         struct file *fp;
  361         struct filedesc *fdp;
  362         struct vnode *vp;
  363         struct exec_vmcmd evc;
  364         struct vm_map_entry *ret;
  365         struct proc *p = l->l_proc;
  366         register_t dontcare;
  367         struct sys_munmap_args cup;
  368         void *va;
  369         int error;
  370 
  371         if ((error = copyin(SCARG(uap, va), (void *)&va, sizeof(va))) != 0)
  372                 return error;
  373 
  374         if (SCARG(uap, findspace) == 0) {
  375                 /* Make some free space XXX probably not The Right Way */
  376                 SCARG(&cup, addr) = va;
  377                 SCARG(&cup, len) = SCARG(uap, size);
  378                 (void)sys_munmap(l, &cup, &dontcare);
  379         }
  380 
  381         fdp = p->p_fd;
  382         fp = fd_getfile(fdp, SCARG(uap, fd));
  383         if (fp == NULL)
  384                 return EBADF;
  385 
  386         FILE_USE(fp);
  387         vp = (struct vnode *)fp->f_data;
  388         vref(vp);
  389 
  390 #ifdef DEBUG_MACH_VM
  391         printf("vm_map_fd: addr = %p len = 0x%08lx\n",
  392             va, (long)SCARG(uap, size));
  393 #endif
  394         bzero(&evc, sizeof(evc));
  395         evc.ev_addr = (u_long)va;
  396         evc.ev_len = SCARG(uap, size);
  397         evc.ev_prot = VM_PROT_ALL;
  398         evc.ev_flags = SCARG(uap, findspace) ? 0 : VMCMD_FIXED;
  399         evc.ev_proc = vmcmd_map_readvn;
  400         evc.ev_offset = SCARG(uap, offset);
  401         evc.ev_vp = vp;
  402 
  403         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  404         if ((error = (*evc.ev_proc)(l, &evc)) != 0) {
  405                 VOP_UNLOCK(vp, 0);
  406 
  407 #ifdef DEBUG_MACH_VM
  408                 printf("mach_sys_map_fd: mapping at %p failed\n", va);
  409 #endif
  410 
  411                 if (SCARG(uap, findspace) == 0)
  412                         goto bad2;
  413 
  414                 vm_map_lock(&p->p_vmspace->vm_map);
  415                 if ((ret = uvm_map_findspace(&p->p_vmspace->vm_map,
  416                     vm_map_min(&p->p_vmspace->vm_map), evc.ev_len,
  417                     (vaddr_t *)&evc.ev_addr, NULL, 0, PAGE_SIZE, 0)) == NULL) {
  418                         vm_map_unlock(&p->p_vmspace->vm_map);
  419                         goto bad2;
  420                 }
  421                 vm_map_unlock(&p->p_vmspace->vm_map);
  422 
  423                 va = (void *)evc.ev_addr;
  424 
  425                 bzero(&evc, sizeof(evc));
  426                 evc.ev_addr = (u_long)va;
  427                 evc.ev_len = SCARG(uap, size);
  428                 evc.ev_prot = VM_PROT_ALL;
  429                 evc.ev_flags = 0;
  430                 evc.ev_proc = vmcmd_map_readvn;
  431                 evc.ev_offset = SCARG(uap, offset);
  432                 evc.ev_vp = vp;
  433 
  434 #ifdef DEBUG_MACH_VM
  435                 printf("mach_sys_map_fd: trying at %p\n", va);
  436 #endif
  437                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  438                 if ((error = (*evc.ev_proc)(l, &evc)) != 0)
  439                         goto bad1;
  440         }
  441 
  442         vput(vp);
  443         FILE_UNUSE(fp, l);
  444 #ifdef DEBUG_MACH_VM
  445         printf("mach_sys_map_fd: mapping at %p\n", (void *)evc.ev_addr);
  446 #endif
  447 
  448         va = (mach_vm_offset_t *)evc.ev_addr;
  449 
  450         if ((error = copyout((void *)&va, SCARG(uap, va), sizeof(va))) != 0)
  451                 return error;
  452 
  453         return 0;
  454 
  455 bad1:
  456         VOP_UNLOCK(vp, 0);
  457 bad2:
  458         vrele(vp);
  459         FILE_UNUSE(fp, l);
  460 #ifdef DEBUG_MACH_VM
  461         printf("mach_sys_map_fd: mapping at %p failed, error = %d\n",
  462             (void *)evc.ev_addr, error);
  463 #endif
  464         return error;
  465 }
  466 
  467 int
  468 mach_vm_inherit(args)
  469         struct mach_trap_args *args;
  470 {
  471         mach_vm_inherit_request_t *req = args->smsg;
  472         mach_vm_inherit_reply_t *rep = args->rmsg;
  473         size_t *msglen = args->rsize;
  474         struct lwp *tl = args->tl;
  475         struct sys_minherit_args cup;
  476         register_t retval;
  477         int error;
  478 
  479         SCARG(&cup, addr) = (void *)req->req_addr;
  480         SCARG(&cup, len) = req->req_size;
  481         /* Flags map well between Mach and NetBSD */
  482         SCARG(&cup, inherit) = req->req_inh;
  483 
  484         if ((error = sys_minherit(tl, &cup, &retval)) != 0)
  485                 return mach_msg_error(args, error);
  486 
  487         *msglen = sizeof(*rep);
  488         mach_set_header(rep, req, *msglen);
  489         mach_set_trailer(rep, *msglen);
  490 
  491         return 0;
  492 }
  493 
  494 int
  495 mach_make_memory_entry_64(args)
  496         struct mach_trap_args *args;
  497 {
  498         mach_make_memory_entry_64_request_t *req = args->smsg;
  499         mach_make_memory_entry_64_reply_t *rep = args->rmsg;
  500         size_t *msglen = args->rsize;
  501         struct lwp *l = args->l;
  502         struct lwp *tl = args->tl;
  503         struct mach_port *mp;
  504         struct mach_right *mr;
  505         struct mach_memory_entry *mme;
  506 
  507         printf("mach_make_memory_entry_64, offset 0x%lx, size 0x%lx\n",
  508             (u_long)req->req_offset, (u_long)req->req_size);
  509 
  510         mp = mach_port_get();
  511         mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
  512         mp->mp_datatype = MACH_MP_MEMORY_ENTRY;
  513 
  514         mme = malloc(sizeof(*mme), M_EMULDATA, M_WAITOK);
  515         mme->mme_proc = tl->l_proc;
  516         mme->mme_offset = req->req_offset;
  517         mme->mme_size = req->req_size;
  518         mp->mp_data = mme;
  519 
  520         mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
  521 
  522         *msglen = sizeof(*rep);
  523         mach_set_header(rep, req, *msglen);
  524         mach_add_port_desc(rep, mr->mr_name);
  525 
  526         rep->rep_size = req->req_size;
  527 
  528         mach_set_trailer(rep, *msglen);
  529 
  530         return 0;
  531 }
  532 
  533 int
  534 mach_vm_region(args)
  535         struct mach_trap_args *args;
  536 {
  537         mach_vm_region_request_t *req = args->smsg;
  538         mach_vm_region_reply_t *rep = args->rmsg;
  539         size_t *msglen = args->rsize;
  540         struct lwp *tl = args->tl;
  541         struct mach_vm_region_basic_info *rbi;
  542         struct vm_map *map;
  543         struct vm_map_entry *vme;
  544         int error;
  545 
  546         /* Sanity check req_count */
  547         if (req->req_count > 9)
  548                 return mach_msg_error(args, EINVAL);
  549 
  550         /*
  551          * MACH_VM_REGION_BASIC_INFO is the only
  552          * supported flavor in Darwin.
  553          */
  554         if (req->req_flavor != MACH_VM_REGION_BASIC_INFO)
  555                 return mach_msg_error(args, EINVAL);
  556         if (req->req_count != (sizeof(*rbi) / sizeof(int))) /* This is 8 */
  557                 return mach_msg_error(args, EINVAL);
  558         *msglen = sizeof(*rep) + ((req->req_count - 9) * sizeof(int));
  559 
  560         map = &tl->l_proc->p_vmspace->vm_map;
  561 
  562         vm_map_lock(map);
  563         error = uvm_map_lookup_entry(map, req->req_addr, &vme);
  564         vm_map_unlock(map);
  565 
  566         if (error == 0)
  567                 return mach_msg_error(args, ENOMEM);
  568 
  569         mach_set_header(rep, req, *msglen);
  570         mach_add_port_desc(rep, 0); /* XXX Why this null name */
  571 
  572         rep->rep_addr = vme->start;
  573         rep->rep_size = vme->end - vme->start;
  574         rep->rep_count = req->req_count;
  575 
  576         rbi = (struct mach_vm_region_basic_info *)&rep->rep_info[0];
  577         rbi->protection = vme->protection;
  578         rbi->inheritance = 1; /* vme->inheritance */
  579         rbi->shared = 0; /* XXX how can we know? */
  580         rbi->offset = vme->offset;
  581         rbi->behavior = MACH_VM_BEHAVIOR_DEFAULT; /* XXX What is it? */
  582         rbi->user_wired_count = vme->wired_count;
  583 
  584         /* XXX Why this? */
  585         *(short *)((u_long)&rbi->user_wired_count + sizeof(short)) = 1;
  586 
  587         mach_set_trailer(rep, *msglen);
  588 
  589         return 0;
  590 }
  591 
  592 int
  593 mach_vm_region_64(args)
  594         struct mach_trap_args *args;
  595 {
  596         mach_vm_region_64_request_t *req = args->smsg;
  597         mach_vm_region_64_reply_t *rep = args->rmsg;
  598         size_t *msglen = args->rsize;
  599         struct lwp *tl = args->tl;
  600         struct mach_vm_region_basic_info_64 *rbi;
  601         struct vm_map *map;
  602         struct vm_map_entry *vme;
  603         int error;
  604 
  605         /* Sanity check req_count */
  606         if (req->req_count > 10)
  607                 return mach_msg_error(args, EINVAL);
  608 
  609         /*
  610          * MACH_VM_REGION_BASIC_INFO is the only
  611          * supported flavor in Darwin.
  612          */
  613         if (req->req_flavor != MACH_VM_REGION_BASIC_INFO)
  614                 return mach_msg_error(args, EINVAL);
  615         if (req->req_count != (sizeof(*rbi) / sizeof(int))) /* This is 8 */
  616                 return mach_msg_error(args, EINVAL);
  617         *msglen = sizeof(*rep) + ((req->req_count - 9) * sizeof(int));
  618 
  619         map = &tl->l_proc->p_vmspace->vm_map;
  620 
  621         vm_map_lock(map);
  622         error = uvm_map_lookup_entry(map, req->req_addr, &vme);
  623         vm_map_unlock(map);
  624 
  625         if (error == 0)
  626                 return mach_msg_error(args, ENOMEM);
  627 
  628         mach_set_header(rep, req, *msglen);
  629         mach_add_port_desc(rep, 0);     /* XXX null port ? */
  630 
  631         rep->rep_size = PAGE_SIZE; /* XXX Why? */
  632         rep->rep_count = req->req_count;
  633 
  634         rbi = (struct mach_vm_region_basic_info_64 *)&rep->rep_info[0];
  635         rbi->protection = vme->protection;
  636         rbi->inheritance = 1; /* vme->inheritance */
  637         rbi->shared = 0; /* XXX how can we know? */
  638         rbi->offset = vme->offset;
  639         rbi->behavior = MACH_VM_BEHAVIOR_DEFAULT; /* XXX What is it? */
  640         rbi->user_wired_count = vme->wired_count;
  641 
  642         /* XXX Why this? */
  643         *(short *)((u_long)&rbi->user_wired_count + sizeof(short)) = 1;
  644 
  645         mach_set_trailer(rep, *msglen);
  646 
  647         return 0;
  648 }
  649 
  650 int
  651 mach_vm_msync(args)
  652         struct mach_trap_args *args;
  653 {
  654         mach_vm_msync_request_t *req = args->smsg;
  655         mach_vm_msync_reply_t *rep = args->rmsg;
  656         size_t *msglen = args->rsize;
  657         struct lwp *tl = args->tl;
  658         struct sys___msync13_args cup;
  659         int error;
  660         register_t dontcare;
  661 
  662         SCARG(&cup, addr) = (void *)req->req_addr;
  663         SCARG(&cup, len) = req->req_size;
  664         SCARG(&cup, flags) = 0;
  665         if (req->req_flags & MACH_VM_SYNC_ASYNCHRONOUS)
  666                 SCARG(&cup, flags) |= MS_ASYNC;
  667         if (req->req_flags & MACH_VM_SYNC_SYNCHRONOUS)
  668                 SCARG(&cup, flags) |= MS_SYNC;
  669         if (req->req_flags & MACH_VM_SYNC_INVALIDATE)
  670                 SCARG(&cup, flags) |= MS_INVALIDATE;
  671 
  672         error = sys___msync13(tl, &cup, &dontcare);
  673 
  674         *msglen = sizeof(*rep);
  675         mach_set_header(rep, req, *msglen);
  676 
  677         rep->rep_retval = native_to_mach_errno[error];
  678 
  679         mach_set_trailer(rep, *msglen);
  680 
  681         return 0;
  682 }
  683 
  684 /* XXX Do it for remote task */
  685 int
  686 mach_vm_copy(args)
  687         struct mach_trap_args *args;
  688 {
  689         mach_vm_copy_request_t *req = args->smsg;
  690         mach_vm_copy_reply_t *rep = args->rmsg;
  691         size_t *msglen = args->rsize;
  692         char *tmpbuf;
  693         int error;
  694         caddr_t src, dst;
  695         size_t size;
  696 
  697 #ifdef DEBUG_MACH_VM
  698         printf("mach_vm_copy: src = 0x%08lx, size = 0x%08lx, addr = 0x%08lx\n",
  699             (long)req->req_src, (long)req->req_size, (long)req->req_addr);
  700 #endif
  701         if ((req->req_src & (PAGE_SIZE - 1)) ||
  702             (req->req_addr & (PAGE_SIZE - 1)) ||
  703             (req->req_size & (PAGE_SIZE - 1)))
  704                 return mach_msg_error(args, EINVAL);
  705 
  706         src = (caddr_t)req->req_src;
  707         dst = (caddr_t)req->req_addr;
  708         size = (size_t)req->req_size;
  709 
  710         tmpbuf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  711 
  712         /* Is there an easy way of dealing with that efficiently? */
  713         do {
  714                 if ((error = copyin(src, tmpbuf, PAGE_SIZE)) != 0)
  715                         goto out;
  716 
  717                 if ((error = copyout(tmpbuf, dst, PAGE_SIZE)) != 0)
  718                         goto out;
  719 
  720                 src += PAGE_SIZE;
  721                 dst += PAGE_SIZE;
  722                 size -= PAGE_SIZE;
  723         } while (size > 0);
  724 
  725         *msglen = sizeof(*rep);
  726         mach_set_header(rep, req, *msglen);
  727 
  728         rep->rep_retval = 0;
  729 
  730         mach_set_trailer(rep, *msglen);
  731 
  732         free(tmpbuf, M_TEMP);
  733         return 0;
  734 
  735 out:
  736         free(tmpbuf, M_TEMP);
  737         return mach_msg_error(args, error);
  738 }
  739 
  740 int
  741 mach_vm_read(args)
  742         struct mach_trap_args *args;
  743 {
  744         mach_vm_read_request_t *req = args->smsg;
  745         mach_vm_read_reply_t *rep = args->rmsg;
  746         size_t *msglen = args->rsize;
  747         struct lwp *l = args->l;
  748         struct lwp *tl = args->tl;
  749         char *tbuf;
  750         void *addr;
  751         vaddr_t va;
  752         size_t size;
  753         int error;
  754 
  755         size = req->req_size;
  756         va = vm_map_min(&l->l_proc->p_vmspace->vm_map);
  757         if ((error = uvm_map(&l->l_proc->p_vmspace->vm_map, &va,
  758             round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0,
  759             UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL,
  760             UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0) {
  761                 printf("uvm_map error = %d\n", error);
  762                 return mach_msg_error(args, EFAULT);
  763         }
  764 
  765         /*
  766          * Copy the data from the target process to the current process
  767          * This is reasonable for small chunk of data, but we should
  768          * remap COW for areas bigger than a page.
  769          */
  770         tbuf = malloc(size, M_EMULDATA, M_WAITOK);
  771 
  772         addr = (void *)req->req_addr;
  773         if ((error = copyin_proc(tl->l_proc, addr, tbuf, size)) != 0) {
  774                 printf("copyin_proc error = %d, addr = %p, size = %x\n", error, addr, size);
  775                 free(tbuf, M_WAITOK);
  776                 return mach_msg_error(args, EFAULT);
  777         }
  778 
  779         if ((error = copyout(tbuf, (void *)va, size)) != 0) {
  780                 printf("copyout error = %d\n", error);
  781                 free(tbuf, M_WAITOK);
  782                 return mach_msg_error(args, EFAULT);
  783         }
  784 
  785 #ifdef KTRACE
  786         if (KTRPOINT(l->l_proc, KTR_MOOL) && error == 0)
  787                 ktrmool(l, tbuf, size, (void *)va);
  788 #endif
  789 
  790         free(tbuf, M_WAITOK);
  791 
  792         *msglen = sizeof(*rep);
  793         mach_set_header(rep, req, *msglen);
  794         mach_add_ool_desc(rep, (void *)va, size);
  795 
  796         rep->rep_count = size;
  797 
  798         mach_set_trailer(rep, *msglen);
  799 
  800         return 0;
  801 }
  802 
  803 int
  804 mach_vm_write(args)
  805         struct mach_trap_args *args;
  806 {
  807         mach_vm_write_request_t *req = args->smsg;
  808         mach_vm_write_reply_t *rep = args->rmsg;
  809         size_t *msglen = args->rsize;
  810 #ifdef KTRACE
  811         struct lwp *l = args->l;
  812 #endif
  813         struct lwp *tl = args->tl;
  814         size_t size;
  815         void *addr;
  816         char *tbuf;
  817         int error;
  818 
  819 #ifdef DEBUG_MACH
  820         if (req->req_body.msgh_descriptor_count != 1)
  821                 printf("mach_vm_write: OOL descriptor count is not 1\n");
  822 #endif
  823 
  824         /*
  825          * Copy the data from the current process to the target process
  826          * This is reasonable for small chunk of data, but we should
  827          * remap COW for areas bigger than a page.
  828          */
  829         size = req->req_data.size;
  830         tbuf = malloc(size, M_EMULDATA, M_WAITOK);
  831 
  832         if ((error = copyin(req->req_data.address, tbuf, size)) != 0) {
  833                 printf("copyin error = %d\n", error);
  834                 free(tbuf, M_WAITOK);
  835                 return mach_msg_error(args, EFAULT);
  836         }
  837 
  838         addr = (void *)req->req_addr;
  839         if ((error = copyout_proc(tl->l_proc, tbuf, addr, size)) != 0) {
  840                 printf("copyout_proc error = %d\n", error);
  841                 free(tbuf, M_WAITOK);
  842                 return mach_msg_error(args, EFAULT);
  843         }
  844 
  845 #ifdef KTRACE
  846         if (KTRPOINT(l->l_proc, KTR_MOOL) && error == 0)
  847                 ktrmool(l, tbuf, size, (void *)addr);
  848 #endif
  849 
  850         free(tbuf, M_WAITOK);
  851 
  852         *msglen = sizeof(*rep);
  853         mach_set_header(rep, req, *msglen);
  854 
  855         rep->rep_retval = 0;
  856 
  857         mach_set_trailer(rep, *msglen);
  858 
  859         return 0;
  860 }
  861 
  862 int
  863 mach_vm_machine_attribute(args)
  864         struct mach_trap_args *args;
  865 {
  866         mach_vm_machine_attribute_request_t *req = args->smsg;
  867         mach_vm_machine_attribute_reply_t *rep = args->rmsg;
  868         size_t *msglen = args->rsize;
  869         struct lwp *tl = args->tl;
  870         int error = 0;
  871         int attribute, value;
  872 
  873         attribute = req->req_attribute;
  874         value = req->req_value;
  875 
  876         switch (attribute) {
  877         case MACH_MATTR_CACHE:
  878                 switch(value) {
  879                 case MACH_MATTR_VAL_CACHE_FLUSH:
  880                 case MACH_MATTR_VAL_DCACHE_FLUSH:
  881                 case MACH_MATTR_VAL_ICACHE_FLUSH:
  882                 case MACH_MATTR_VAL_CACHE_SYNC:
  883                         error = mach_vm_machine_attribute_machdep(tl,
  884                             req->req_addr, req->req_size, &value);
  885                         break;
  886                 default:
  887 #ifdef DEBUG_MACH
  888                         printf("unimplemented value %d\n", req->req_value);
  889 #endif
  890                         error = EINVAL;
  891                         break;
  892                 }
  893                 break;
  894 
  895         case MACH_MATTR_MIGRATE:
  896         case MACH_MATTR_REPLICATE:
  897         default:
  898 #ifdef DEBUG_MACH
  899                 printf("unimplemented attribute %d\n", req->req_attribute);
  900 #endif
  901                 error = EINVAL;
  902                 break;
  903         }
  904 
  905         *msglen = sizeof(*rep);
  906         mach_set_header(rep, req, *msglen);
  907 
  908         rep->rep_retval = native_to_mach_errno[error];
  909         if (error != 0)
  910                 rep->rep_value = value;
  911 
  912         mach_set_trailer(rep, *msglen);
  913 
  914         return 0;
  915 }

Cache object: 27a0e60c6bf4f6e5ab7c6c9d62a7f917


[ 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.