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/i386/linux/linux_misc.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 /*-
    2  * Copyright (c) 1994-1995 Søren Schmidt
    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
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer
   10  *    in this position and unchanged.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software withough specific prior written permission
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD: src/sys/i386/linux/linux_misc.c,v 1.20.2.7 1999/09/05 08:14:16 peter Exp $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/sysproto.h>
   34 #include <sys/kernel.h>
   35 #include <sys/exec.h>
   36 #include <sys/mman.h>
   37 #include <sys/proc.h>
   38 #include <sys/dirent.h>
   39 #include <sys/file.h>
   40 #include <sys/filedesc.h>
   41 #include <sys/ioctl.h>
   42 #include <sys/imgact_aout.h>
   43 #include <sys/mount.h>
   44 #include <sys/namei.h>
   45 #include <sys/resource.h>
   46 #include <sys/resourcevar.h>
   47 #include <sys/stat.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/times.h>
   50 #include <sys/utsname.h>
   51 #include <sys/vnode.h>
   52 #include <sys/wait.h>
   53 #include <sys/time.h>
   54 
   55 #include <vm/vm.h>
   56 #include <vm/vm_param.h>
   57 #include <vm/pmap.h>
   58 #include <vm/lock.h>
   59 #include <vm/vm_kern.h>
   60 #include <vm/vm_prot.h>
   61 #include <vm/vm_map.h>
   62 #include <vm/vm_extern.h>
   63 
   64 #include <machine/psl.h>
   65 #include <machine/frame.h>
   66 
   67 #include <machine/frame.h>
   68 #include <machine/psl.h>
   69 #include <machine/reg.h>
   70 
   71 #include <i386/linux/linux.h>
   72 #include <i386/linux/linux_proto.h>
   73 #include <i386/linux/linux_util.h>
   74 
   75 int
   76 linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
   77 {
   78     struct itimerval it, old_it;
   79     struct timeval tv;
   80     int s;
   81 
   82 #ifdef DEBUG
   83     printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs);
   84 #endif
   85     it.it_value.tv_sec = (long)args->secs;
   86     it.it_value.tv_usec = 0;
   87     it.it_interval.tv_sec = 0;
   88     it.it_interval.tv_usec = 0;
   89     s = splclock(); /* XXX Still needed ? */
   90     old_it = p->p_realtimer;
   91     tv = time;
   92     if (timerisset(&old_it.it_value))
   93         if (timercmp(&old_it.it_value, &tv, <))
   94             timerclear(&old_it.it_value);
   95         else
   96             timevalsub(&old_it.it_value, &tv);
   97     splx(s);
   98     if (itimerfix(&it.it_value) || itimerfix(&it.it_interval))
   99         return EINVAL;
  100     s = splclock();
  101     untimeout(realitexpire, (caddr_t)p);
  102     tv = time;
  103     if (timerisset(&it.it_value)) {
  104         timevaladd(&it.it_value, &tv);
  105         timeout(realitexpire, (caddr_t)p, hzto(&it.it_value));
  106     }
  107     p->p_realtimer = it;
  108     splx(s);
  109     if (old_it.it_value.tv_usec)
  110         old_it.it_value.tv_sec++;
  111     *retval = old_it.it_value.tv_sec;
  112     return 0;
  113 }
  114 
  115 int
  116 linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
  117 {
  118 #if 0
  119     struct vmspace *vm = p->p_vmspace;
  120     vm_offset_t new, old;
  121     int error;
  122 
  123     if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr)
  124         return EINVAL;
  125     if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr)
  126         > p->p_rlimit[RLIMIT_DATA].rlim_cur)
  127         return ENOMEM;
  128 
  129     old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize);
  130     new = round_page((vm_offset_t)args->dsend);
  131     *retval = old;
  132     if ((new-old) > 0) {
  133         if (swap_pager_full)
  134             return ENOMEM;
  135         error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE,
  136                         VM_PROT_ALL, VM_PROT_ALL, 0);
  137         if (error)
  138             return error;
  139         vm->vm_dsize += btoc((new-old));
  140         *retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize));
  141     }
  142     return 0;
  143 #else
  144     struct vmspace *vm = p->p_vmspace;
  145     vm_offset_t new, old;
  146     struct obreak_args /* {
  147         char * nsize;
  148     } */ tmp;
  149 
  150 #ifdef DEBUG
  151     printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend);
  152 #endif
  153     old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
  154     new = (vm_offset_t)args->dsend;
  155     tmp.nsize = (char *) new;
  156     if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval))
  157         *retval = (int)new;
  158     else
  159         *retval = (int)old;
  160 
  161     return 0;
  162 #endif
  163 }
  164 
  165 int
  166 linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
  167 {
  168     struct nameidata ni;
  169     struct vnode *vp;
  170     struct exec *a_out;
  171     struct vattr attr;
  172     vm_offset_t vmaddr;
  173     unsigned long file_offset;
  174     vm_offset_t buffer;
  175     unsigned long bss_size;
  176     int error;
  177     caddr_t sg;
  178     int locked;
  179 
  180     sg = stackgap_init();
  181     CHECKALTEXIST(p, &sg, args->library);
  182 
  183 #ifdef DEBUG
  184     printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library);
  185 #endif
  186 
  187     a_out = NULL;
  188     locked = 0;
  189     vp = NULL;
  190 
  191     NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, args->library, p);
  192     if (error = namei(&ni))
  193         goto cleanup;
  194 
  195     vp = ni.ni_vp;
  196     if (vp == NULL) {
  197         error = ENOEXEC;        /* ?? */
  198         goto cleanup;
  199     }
  200 
  201     /*
  202      * From here on down, we have a locked vnode that must be unlocked.
  203      */
  204     locked++;
  205 
  206     /*
  207      * Writable?
  208      */
  209     if (vp->v_writecount) {
  210         error = ETXTBSY;
  211         goto cleanup;
  212     }
  213 
  214     /*
  215      * Executable?
  216      */
  217     if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p))
  218         goto cleanup;
  219 
  220     if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
  221         ((attr.va_mode & 0111) == 0) ||
  222         (attr.va_type != VREG)) {
  223             error = ENOEXEC;
  224             goto cleanup;
  225     }
  226 
  227     /*
  228      * Sensible size?
  229      */
  230     if (attr.va_size == 0) {
  231         error = ENOEXEC;
  232         goto cleanup;
  233     }
  234 
  235     /*
  236      * Can we access it?
  237      */
  238     if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
  239         goto cleanup;
  240 
  241     if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p))
  242         goto cleanup;
  243 
  244     /*
  245      * Lock no longer needed
  246      */
  247     VOP_UNLOCK(vp);
  248     locked = 0;
  249 
  250     /*
  251      * Pull in executable header into kernel_map
  252      */
  253     error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE,
  254                     VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0);
  255     if (error)
  256         goto cleanup;
  257 
  258     /*
  259      * Is it a Linux binary ?
  260      */
  261     if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
  262         error = ENOEXEC;
  263         goto cleanup;
  264     }
  265 
  266     /* While we are here, we should REALLY do some more checks */
  267 
  268     /*
  269      * Set file/virtual offset based on a.out variant.
  270      */
  271     switch ((int)(a_out->a_magic & 0xffff)) {
  272     case 0413:  /* ZMAGIC */
  273         file_offset = 1024;
  274         break;
  275     case 0314:  /* QMAGIC */
  276         file_offset = 0;
  277         break;
  278     default:
  279         error = ENOEXEC;
  280         goto cleanup;
  281     }
  282 
  283     bss_size = round_page(a_out->a_bss);
  284 
  285     /*
  286      * Check various fields in header for validity/bounds.
  287      */
  288     if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
  289         error = ENOEXEC;
  290         goto cleanup;
  291     }
  292 
  293     /* text + data can't exceed file size */
  294     if (a_out->a_data + a_out->a_text > attr.va_size) {
  295         error = EFAULT;
  296         goto cleanup;
  297     }
  298 
  299     /*
  300      * text/data/bss must not exceed limits
  301      * XXX: this is not complete. it should check current usage PLUS
  302      * the resources needed by this library.
  303      */
  304     if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ ||
  305         a_out->a_data+bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) {
  306         error = ENOMEM;
  307         goto cleanup;
  308     }
  309 
  310     /*
  311      * prevent more writers
  312      */
  313     vp->v_flag |= VTEXT;
  314 
  315     /*
  316      * Check if file_offset page aligned,.
  317      * Currently we cannot handle misalinged file offsets,
  318      * and so we read in the entire image (what a waste).
  319      */
  320     if (file_offset & PAGE_MASK) {
  321 #ifdef DEBUG
  322 printf("uselib: Non page aligned binary %d\n", file_offset);
  323 #endif
  324         /*
  325          * Map text+data read/write/execute
  326          */
  327 
  328         /* a_entry is the load address and is page aligned */
  329         vmaddr = trunc_page(a_out->a_entry);
  330 
  331         /* get anon user mapping, read+write+execute */
  332         error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
  333                             a_out->a_text + a_out->a_data, FALSE,
  334                             VM_PROT_ALL, VM_PROT_ALL, 0);
  335         if (error)
  336             goto cleanup;
  337 
  338         /* map file into kernel_map */
  339         error = vm_mmap(kernel_map, &buffer,
  340                         round_page(a_out->a_text + a_out->a_data + file_offset),
  341                         VM_PROT_READ, VM_PROT_READ, 0,
  342                         (caddr_t)vp, trunc_page(file_offset));
  343         if (error)
  344             goto cleanup;
  345 
  346         /* copy from kernel VM space to user space */
  347         error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
  348                         a_out->a_text + a_out->a_data);
  349 
  350         /* release temporary kernel space */
  351         vm_map_remove(kernel_map, buffer,
  352                       buffer + round_page(a_out->a_text + a_out->a_data + file_offset));
  353 
  354         if (error)
  355             goto cleanup;
  356     }
  357     else {
  358 #ifdef DEBUG
  359 printf("uselib: Page aligned binary %d\n", file_offset);
  360 #endif
  361         /*
  362          * for QMAGIC, a_entry is 20 bytes beyond the load address
  363          * to skip the executable header
  364          */
  365         vmaddr = trunc_page(a_out->a_entry);
  366 
  367         /*
  368          * Map it all into the process's space as a single copy-on-write
  369          * "data" segment.
  370          */
  371         error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
  372                         a_out->a_text + a_out->a_data,
  373                         VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
  374                         (caddr_t)vp, file_offset);
  375         if (error)
  376             goto cleanup;
  377     }
  378 #ifdef DEBUG
  379 printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
  380 #endif
  381     if (bss_size != 0) {
  382         /*
  383          * Calculate BSS start address
  384          */
  385         vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data;
  386 
  387         /*
  388          * allocate some 'anon' space
  389          */
  390         error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
  391                             bss_size, FALSE,
  392                             VM_PROT_ALL, VM_PROT_ALL, 0);
  393         if (error)
  394             goto cleanup;
  395     }
  396 
  397 cleanup:
  398     /*
  399      * Unlock vnode if needed
  400      */
  401     if (locked)
  402         VOP_UNLOCK(vp);
  403 
  404     /*
  405      * Release the kernel mapping.
  406      */
  407     if (a_out)
  408         vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE);
  409 
  410     return error;
  411 }
  412 
  413 /* XXX move */
  414 struct linux_select_argv {
  415         int nfds;
  416         fd_set *readfds;
  417         fd_set *writefds;
  418         fd_set *exceptfds;
  419         struct timeval *timeout;
  420 };
  421 
  422 int
  423 linux_select(struct proc *p, struct linux_select_args *args, int *retval)
  424 {
  425     struct linux_select_argv linux_args;
  426     struct linux_newselect_args newsel;
  427     int error;
  428 
  429 #ifdef SELECT_DEBUG
  430     printf("Linux-emul(%d): select(%x)\n",
  431            p->p_pid, args->ptr);
  432 #endif
  433     if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
  434                         sizeof(linux_args))))
  435         return error;
  436 
  437     newsel.nfds = linux_args.nfds;
  438     newsel.readfds = linux_args.readfds;
  439     newsel.writefds = linux_args.writefds;
  440     newsel.exceptfds = linux_args.exceptfds;
  441     newsel.timeout = linux_args.timeout;
  442 
  443     return linux_newselect(p, &newsel, retval);
  444 }
  445 
  446 int
  447 linux_newselect(struct proc *p, struct linux_newselect_args *args, int *retval)
  448 {
  449     struct select_args bsa;
  450     struct timeval tv0, tv1, utv, *tvp;
  451     caddr_t sg;
  452     int error;
  453 
  454 #ifdef DEBUG
  455     printf("Linux-emul(%d): newselect(%d, %x, %x, %x, %x)\n",
  456                p->p_pid, args->nfds, args->readfds, args->writefds,
  457                args->exceptfds, args->timeout);
  458 #endif
  459     error = 0;
  460     bsa.nd = args->nfds;
  461     bsa.in = args->readfds;
  462     bsa.ou = args->writefds;
  463     bsa.ex = args->exceptfds;
  464     bsa.tv = args->timeout;
  465 
  466     /*
  467      * Store current time for computation of the amount of
  468      * time left.
  469      */
  470     if (args->timeout) {
  471         if ((error = copyin(args->timeout, &utv, sizeof(utv))))
  472             goto select_out;
  473 #ifdef DEBUG
  474         printf("Linux-emul(%d): incoming timeout (%d/%d)\n",
  475                p->p_pid, utv.tv_sec, utv.tv_usec);
  476 #endif
  477         if (itimerfix(&utv)) {
  478             /*
  479              * The timeval was invalid.  Convert it to something
  480              * valid that will act as it does under Linux.
  481              */
  482             sg = stackgap_init();
  483             tvp = stackgap_alloc(&sg, sizeof(utv));
  484             utv.tv_sec += utv.tv_usec / 1000000;
  485             utv.tv_usec %= 1000000;
  486             if (utv.tv_usec < 0) {
  487                 utv.tv_sec -= 1;
  488                 utv.tv_usec += 1000000;
  489             }
  490             if (utv.tv_sec < 0)
  491                 timerclear(&utv);
  492             if ((error = copyout(&utv, tvp, sizeof(utv))))
  493                 goto select_out;
  494             bsa.tv = tvp;
  495         }
  496         microtime(&tv0);
  497     }
  498 
  499     error = select(p, &bsa, retval);
  500 #ifdef DEBUG
  501     printf("Linux-emul(%d): real select returns %d\n",
  502                p->p_pid, error);
  503 #endif
  504 
  505     if (error) {
  506         /*
  507          * See fs/select.c in the Linux kernel.  Without this,
  508          * Maelstrom doesn't work.
  509          */
  510         if (error == ERESTART)
  511             error = EINTR;
  512         goto select_out;
  513     }
  514 
  515     if (args->timeout) {
  516         if (*retval) {
  517             /*
  518              * Compute how much time was left of the timeout,
  519              * by subtracting the current time and the time
  520              * before we started the call, and subtracting
  521              * that result from the user-supplied value.
  522              */
  523             microtime(&tv1);
  524             timevalsub(&tv1, &tv0);
  525             timevalsub(&utv, &tv1);
  526             if (utv.tv_sec < 0)
  527                 timerclear(&utv);
  528         } else
  529             timerclear(&utv);
  530 #ifdef DEBUG
  531         printf("Linux-emul(%d): outgoing timeout (%d/%d)\n",
  532                p->p_pid, utv.tv_sec, utv.tv_usec);
  533 #endif
  534         if ((error = copyout(&utv, args->timeout, sizeof(utv))))
  535             goto select_out;
  536     }
  537 
  538 select_out:
  539 #ifdef DEBUG
  540     printf("Linux-emul(%d): newselect_out -> %d\n",
  541                p->p_pid, error);
  542 #endif
  543     return error;
  544 }
  545 
  546 int
  547 linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
  548 {
  549     struct proc *curproc;
  550 
  551 #ifdef DEBUG
  552     printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid);
  553 #endif
  554     if (args->pid != p->p_pid) {
  555         if (!(curproc = pfind(args->pid)))
  556             return ESRCH;
  557     }
  558     else
  559         curproc = p;
  560     *retval = curproc->p_pgid;
  561     return 0;
  562 }
  563 
  564 int
  565 linux_fork(struct proc *p, struct linux_fork_args *args, int *retval)
  566 {
  567     int error;
  568 
  569 #ifdef DEBUG
  570     printf("Linux-emul(%d): fork()\n", p->p_pid);
  571 #endif
  572     if (error = fork(p, (struct fork_args *)args, retval))
  573         return error;
  574     if (retval[1] == 1)
  575         retval[0] = 0;
  576     return 0;
  577 }
  578 
  579 /* XXX move */
  580 struct linux_mmap_argv {
  581         linux_caddr_t addr;
  582         int len;
  583         int prot;
  584         int flags;
  585         int fd;
  586         int pos;
  587 };
  588 
  589 int
  590 linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
  591 {
  592     struct mmap_args /* {
  593         caddr_t addr;
  594         size_t len;
  595         int prot;
  596         int flags;
  597         int fd;
  598         long pad;
  599         off_t pos;
  600     } */ bsd_args;
  601     int error;
  602     struct linux_mmap_argv linux_args;
  603 
  604     if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
  605                         sizeof(linux_args))))
  606         return error;
  607 #ifdef DEBUG
  608     printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n",
  609            p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
  610            linux_args.flags, linux_args.fd, linux_args.pos);
  611 #endif
  612     bsd_args.flags = 0;
  613     if (linux_args.flags & LINUX_MAP_SHARED)
  614         bsd_args.flags |= MAP_SHARED;
  615     if (linux_args.flags & LINUX_MAP_PRIVATE)
  616         bsd_args.flags |= MAP_PRIVATE;
  617     if (linux_args.flags & LINUX_MAP_FIXED)
  618         bsd_args.flags |= MAP_FIXED;
  619     if (linux_args.flags & LINUX_MAP_ANON)
  620         bsd_args.flags |= MAP_ANON;
  621     bsd_args.addr = linux_args.addr;
  622     bsd_args.len = linux_args.len;
  623     bsd_args.prot = linux_args.prot | PROT_READ;        /* always required */
  624     bsd_args.fd = linux_args.fd;
  625     bsd_args.pos = linux_args.pos;
  626     bsd_args.pad = 0;
  627     return mmap(p, &bsd_args, retval);
  628 }
  629 
  630 int
  631 linux_mremap(struct proc *p, struct linux_mremap_args *args, int *retval)
  632 {
  633         struct munmap_args /* {
  634                 void *addr;
  635                 size_t len;
  636         } */ bsd_args;
  637         int error = 0;
  638 
  639 #ifdef DEBUG
  640         printf("Linux-emul(%ld): mremap(%p, %08x, %08x, %08x)\n",
  641             (long)p->p_pid, (void *)args->addr, args->old_len, args->new_len,
  642             args->flags);
  643 #endif
  644         args->new_len = round_page(args->new_len);
  645         args->old_len = round_page(args->old_len);
  646 
  647         if (args->new_len > args->old_len) {
  648                 *retval = 0;
  649                 return ENOMEM;
  650         }
  651 
  652         if (args->new_len < args->old_len) {
  653                 bsd_args.addr = args->addr + args->new_len;
  654                 bsd_args.len = args->old_len - args->new_len;
  655                 error = munmap(p, &bsd_args, retval);
  656         }
  657 
  658         *retval = error ? 0 : (int)args->addr;
  659         return error;
  660 }
  661 
  662 int
  663 linux_msync(struct proc *p, struct linux_msync_args *args, int *retval)
  664 {
  665         struct msync_args bsd_args;
  666 
  667         bsd_args.addr = args->addr;
  668         bsd_args.len = args->len;
  669         bsd_args.flags = 0;     /* XXX ignore */
  670 
  671         return msync(p, &bsd_args, retval);
  672 }
  673 
  674 int
  675 linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
  676 {
  677     int error;
  678 
  679 #ifdef DEBUG
  680     printf("Linux-emul(%d): pipe(*)\n", p->p_pid);
  681 #endif
  682     if (error = pipe(p, 0, retval))
  683         return error;
  684     if (error = copyout(retval, args->pipefds, 2*sizeof(int)))
  685         return error;
  686     *retval = 0;
  687     return 0;
  688 }
  689 
  690 int
  691 linux_time(struct proc *p, struct linux_time_args *args, int *retval)
  692 {
  693     struct timeval tv;
  694     linux_time_t tm;
  695     int error;
  696 
  697 #ifdef DEBUG
  698     printf("Linux-emul(%d): time(*)\n", p->p_pid);
  699 #endif
  700     microtime(&tv);
  701     tm = tv.tv_sec;
  702     if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t))))
  703         return error;
  704     *retval = tm;
  705     return 0;
  706 }
  707 
  708 struct linux_times_argv {
  709     long    tms_utime;
  710     long    tms_stime;
  711     long    tms_cutime;
  712     long    tms_cstime;
  713 };
  714 
  715 #define CLK_TCK 100     /* Linux uses 100 */
  716 #define CONVTCK(r)      (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
  717 
  718 int
  719 linux_times(struct proc *p, struct linux_times_args *args, int *retval)
  720 {
  721     struct timeval tv;
  722     struct linux_times_argv tms;
  723     struct rusage ru;
  724     int error;
  725 
  726 #ifdef DEBUG
  727     printf("Linux-emul(%d): times(*)\n", p->p_pid);
  728 #endif
  729     calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
  730 
  731     tms.tms_utime = CONVTCK(ru.ru_utime);
  732     tms.tms_stime = CONVTCK(ru.ru_stime);
  733 
  734     tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
  735     tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
  736 
  737     if ((error = copyout((caddr_t)&tms, (caddr_t)args->buf,
  738                     sizeof(struct linux_times_argv))))
  739         return error;
  740 
  741     microtime(&tv);
  742     timevalsub(&tv, &boottime);
  743     *retval = (int)CONVTCK(tv);
  744     return 0;
  745 }
  746 
  747 /* XXX move */
  748 struct linux_newuname_t {
  749     char sysname[65];
  750     char nodename[65];
  751     char release[65];
  752     char version[65];
  753     char machine[65];
  754     char domainname[65];
  755 };
  756 
  757 int
  758 linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
  759 {
  760     struct linux_newuname_t linux_newuname;
  761 
  762 #ifdef DEBUG
  763     printf("Linux-emul(%d): newuname(*)\n", p->p_pid);
  764 #endif
  765     bzero(&linux_newuname, sizeof(struct linux_newuname_args));
  766     strncpy(linux_newuname.sysname, ostype, 64);
  767     strncpy(linux_newuname.nodename, hostname, 64);
  768     strncpy(linux_newuname.release, osrelease, 64);
  769     strncpy(linux_newuname.version, version, 64);
  770     strncpy(linux_newuname.machine, machine, 64);
  771     strncpy(linux_newuname.domainname, domainname, 64);
  772     return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf,
  773                     sizeof(struct linux_newuname_t)));
  774 }
  775 
  776 struct linux_utimbuf {
  777         linux_time_t l_actime;
  778         linux_time_t l_modtime;
  779 };
  780 
  781 int
  782 linux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
  783 {
  784     struct utimes_args /* {
  785         char    *path;
  786         struct  timeval *tptr;
  787     } */ bsdutimes;
  788     struct timeval tv[2], *tvp;
  789     struct linux_utimbuf lut;
  790     int error;
  791     caddr_t sg;
  792 
  793     sg = stackgap_init();
  794     CHECKALTEXIST(p, &sg, args->fname);
  795 
  796 #ifdef DEBUG
  797     printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname);
  798 #endif
  799     if (args->times) {
  800         if ((error = copyin(args->times, &lut, sizeof lut)))
  801             return error;
  802         tv[0].tv_sec = lut.l_actime;
  803         tv[0].tv_usec = 0;
  804         tv[1].tv_sec = lut.l_modtime;
  805         tv[1].tv_usec = 0;
  806         /* so that utimes can copyin */
  807         tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv));
  808         if ((error = copyout(tv, tvp, sizeof(tv))))
  809             return error;
  810         bsdutimes.tptr = tvp;
  811     } else
  812         bsdutimes.tptr = NULL;
  813 
  814     bsdutimes.path = args->fname;
  815     return utimes(p, &bsdutimes, retval);
  816 }
  817 
  818 int
  819 linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
  820 {
  821     struct wait_args /* {
  822         int pid;
  823         int *status;
  824         int options;
  825         struct  rusage *rusage;
  826     } */ tmp;
  827     int error, tmpstat;
  828 
  829 #ifdef DEBUG
  830     printf("Linux-emul(%d): waitpid(%d, 0x%x, %d)\n",
  831            p->p_pid, args->pid, args->status, args->options);
  832 #endif
  833     tmp.pid = args->pid;
  834     tmp.status = args->status;
  835     tmp.options = args->options;
  836     tmp.rusage = NULL;
  837 
  838     if (error = wait4(p, &tmp, retval))
  839         return error;
  840     if (args->status) {
  841         if (error = copyin(args->status, &tmpstat, sizeof(int)))
  842             return error;
  843         if (WIFSIGNALED(tmpstat))
  844             tmpstat = (tmpstat & 0xffffff80) |
  845                       bsd_to_linux_signal[WTERMSIG(tmpstat)];
  846         else if (WIFSTOPPED(tmpstat))
  847             tmpstat = (tmpstat & 0xffff00ff) |
  848                       (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
  849         return copyout(&tmpstat, args->status, sizeof(int));
  850     } else
  851         return 0;
  852 }
  853 
  854 int
  855 linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
  856 {
  857     struct wait_args /* {
  858         int pid;
  859         int *status;
  860         int options;
  861         struct  rusage *rusage;
  862     } */ tmp;
  863     int error, tmpstat;
  864 
  865 #ifdef DEBUG
  866     printf("Linux-emul(%d): wait4(%d, 0x%x, %d, 0x%x)\n",
  867            p->p_pid, args->pid, args->status, args->options, args->rusage);
  868 #endif
  869     tmp.pid = args->pid;
  870     tmp.status = args->status;
  871     tmp.options = args->options;
  872     tmp.rusage = args->rusage;
  873 
  874     if (error = wait4(p, &tmp, retval))
  875         return error;
  876 
  877     p->p_siglist &= ~sigmask(SIGCHLD);
  878 
  879     if (args->status) {
  880         if (error = copyin(args->status, &tmpstat, sizeof(int)))
  881             return error;
  882         if (WIFSIGNALED(tmpstat))
  883             tmpstat = (tmpstat & 0xffffff80) |
  884                   bsd_to_linux_signal[WTERMSIG(tmpstat)];
  885         else if (WIFSTOPPED(tmpstat))
  886             tmpstat = (tmpstat & 0xffff00ff) |
  887                   (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
  888         return copyout(&tmpstat, args->status, sizeof(int));
  889     } else
  890         return 0;
  891 }
  892 
  893 int
  894 linux_mknod(struct proc *p, struct linux_mknod_args *args, int *retval)
  895 {
  896         caddr_t sg;
  897         struct mknod_args bsd_mknod;
  898         struct mkfifo_args bsd_mkfifo;
  899 
  900         sg = stackgap_init();
  901 
  902         CHECKALTCREAT(p, &sg, args->path);
  903 
  904 #ifdef DEBUG
  905         printf("Linux-emul(%d): mknod(%s, %d, %d)\n",
  906            p->p_pid, args->path, args->mode, args->dev);
  907 #endif
  908 
  909         if (args->mode & S_IFIFO) {
  910                 bsd_mkfifo.path = args->path;
  911                 bsd_mkfifo.mode = args->mode;
  912                 return mkfifo(p, &bsd_mkfifo, retval);
  913         } else {
  914                 bsd_mknod.path = args->path;
  915                 bsd_mknod.mode = args->mode;
  916                 bsd_mknod.dev = args->dev;
  917                 return mknod(p, &bsd_mknod, retval);
  918         }
  919 }
  920 
  921 /*
  922  * UGH! This is just about the dumbest idea I've ever heard!!
  923  */
  924 int
  925 linux_personality(struct proc *p, struct linux_personality_args *args,
  926                   int *retval)
  927 {
  928 #ifdef DEBUG
  929         printf("Linux-emul(%d): personality(%d)\n",
  930            p->p_pid, args->per);
  931 #endif
  932         if (args->per != 0)
  933                 return EINVAL;
  934 
  935         /* Yes Jim, it's still a Linux... */
  936         *retval = 0;
  937         return 0;
  938 }
  939 
  940 /*
  941  * Wrappers for get/setitimer for debugging..
  942  */
  943 int
  944 linux_setitimer(struct proc *p, struct linux_setitimer_args *args, int *retval)
  945 {
  946         struct setitimer_args bsa;
  947         struct itimerval foo;
  948         int error;
  949 
  950 #ifdef DEBUG
  951         printf("Linux-emul(%d): setitimer(%08x, %08x)\n",
  952            p->p_pid, args->itv, args->oitv);
  953 #endif
  954         bsa.which = args->which;
  955         bsa.itv = args->itv;
  956         bsa.oitv = args->oitv;
  957         if (args->itv) {
  958             if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo,
  959                         sizeof(foo))))
  960                 return error;
  961 #ifdef DEBUG
  962             printf("setitimer: value: sec: %d, usec: %d\n", foo.it_value.tv_sec, foo.it_value.tv_usec);
  963             printf("setitimer: interval: sec: %d, usec: %d\n", foo.it_interval.tv_sec, foo.it_interval.tv_usec);
  964 #endif
  965         }
  966         return setitimer(p, &bsa, retval);
  967 }
  968 
  969 int
  970 linux_getitimer(struct proc *p, struct linux_getitimer_args *args, int *retval)
  971 {
  972         struct getitimer_args bsa;
  973 #ifdef DEBUG
  974         printf("Linux-emul(%d): getitimer(%08x)\n",
  975            p->p_pid, args->itv);
  976 #endif
  977         bsa.which = args->which;
  978         bsa.itv = args->itv;
  979         return getitimer(p, &bsa, retval);
  980 }
  981 
  982 int
  983 linux_iopl(struct proc *p, struct linux_iopl_args *args, int *retval)
  984 {
  985         int error;
  986 
  987         error = suser(p->p_ucred, &p->p_acflag);
  988         if (error != 0)
  989             return error;
  990         if (securelevel > 0)
  991             return EPERM;
  992         ((struct trapframe *)(p->p_md.md_regs))->tf_eflags |= PSL_IOPL;
  993         return 0;
  994 }
  995 
  996 int
  997 linux_nice(struct proc *p, struct linux_nice_args *args, int *retval)
  998 {
  999         struct setpriority_args bsd_args;
 1000 
 1001         bsd_args.which = PRIO_PROCESS;
 1002         bsd_args.who = 0;       /* current process */
 1003         bsd_args.prio = args->inc;
 1004         return setpriority(p, &bsd_args, retval);
 1005 }

Cache object: d7543815fd9f260a2827790925d5b2af


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