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/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$
   29  */
   30 
   31 #include "opt_compat.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/fcntl.h>
   36 #include <sys/imgact_aout.h>
   37 #include <sys/kernel.h>
   38 #include <sys/lock.h>
   39 #include <sys/mman.h>
   40 #include <sys/mount.h>
   41 #include <sys/namei.h>
   42 #include <sys/poll.h>
   43 #include <sys/proc.h>
   44 #include <sys/blist.h>
   45 #include <sys/reboot.h>
   46 #include <sys/resourcevar.h>
   47 #include <sys/signalvar.h>
   48 #include <sys/stat.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/sysproto.h>
   51 #include <sys/time.h>
   52 #include <sys/unistd.h>
   53 #include <sys/vmmeter.h>
   54 #include <sys/vnode.h>
   55 #include <sys/wait.h>
   56 
   57 #include <vm/vm.h>
   58 #include <vm/pmap.h>
   59 #include <vm/vm_kern.h>
   60 #include <vm/vm_map.h>
   61 #include <vm/vm_extern.h>
   62 #include <vm/vm_object.h>
   63 #include <vm/vm_zone.h>
   64 #include <vm/swap_pager.h>
   65 
   66 #include <machine/frame.h>
   67 #include <machine/limits.h>
   68 #include <machine/psl.h>
   69 #include <machine/sysarch.h>
   70 #ifdef __i386__
   71 #include <machine/segments.h>
   72 #endif
   73 
   74 #include <posix4/sched.h>
   75 
   76 #include <machine/../linux/linux.h>
   77 #include <machine/../linux/linux_proto.h>
   78 #include <compat/linux/linux_mib.h>
   79 #include <compat/linux/linux_util.h>
   80 
   81 #ifdef __alpha__
   82 #define BSD_TO_LINUX_SIGNAL(sig)       (sig)
   83 #else
   84 #define BSD_TO_LINUX_SIGNAL(sig)        \
   85         (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
   86 #endif
   87 
   88 #ifndef __alpha__
   89 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
   90         RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
   91         RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
   92         RLIMIT_MEMLOCK, -1
   93 };
   94 #endif /*!__alpha__*/
   95 
   96 struct l_sysinfo {
   97         l_long          uptime;         /* Seconds since boot */
   98         l_ulong         loads[3];       /* 1, 5, and 15 minute load averages */
   99         l_ulong         totalram;       /* Total usable main memory size */
  100         l_ulong         freeram;        /* Available memory size */
  101         l_ulong         sharedram;      /* Amount of shared memory */
  102         l_ulong         bufferram;      /* Memory used by buffers */
  103         l_ulong         totalswap;      /* Total swap space size */
  104         l_ulong         freeswap;       /* swap space still available */
  105         l_ushort        procs;          /* Number of current processes */
  106         char            _f[22];         /* Pads structure to 64 bytes */
  107 };
  108 #ifndef __alpha__
  109 int
  110 linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args)
  111 {
  112         struct l_sysinfo sysinfo;
  113         vm_object_t object;
  114         int i;
  115         struct timespec ts;
  116 
  117         /* Uptime is copied out of print_uptime() in kern_shutdown.c */
  118         getnanouptime(&ts);
  119         i = 0;
  120         if (ts.tv_sec >= 86400) {
  121                 ts.tv_sec %= 86400;
  122                 i = 1;
  123         }
  124         if (i || ts.tv_sec >= 3600) {
  125                 ts.tv_sec %= 3600;
  126                 i = 1;
  127         }
  128         if (i || ts.tv_sec >= 60) {
  129                 ts.tv_sec %= 60;
  130                 i = 1;
  131         }
  132         sysinfo.uptime=ts.tv_sec;
  133 
  134         /* Use the information from the mib to get our load averages */
  135         for (i = 0; i < 3; i++)
  136                 sysinfo.loads[i] = averunnable.ldavg[i];
  137 
  138         sysinfo.totalram = physmem * PAGE_SIZE;
  139         sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE;
  140 
  141         sysinfo.sharedram = 0;
  142         for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
  143              object = TAILQ_NEXT(object, object_list))
  144                 if (object->shadow_count > 1)
  145                         sysinfo.sharedram += object->resident_page_count;
  146 
  147         sysinfo.sharedram *= PAGE_SIZE;
  148         sysinfo.bufferram = 0;
  149 
  150         if (swapblist == NULL) {
  151                 sysinfo.totalswap= 0;
  152                 sysinfo.freeswap = 0;
  153         } else {
  154                 sysinfo.totalswap = swapblist->bl_blocks * 1024;
  155                 sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
  156         }
  157 
  158         sysinfo.procs = 20; /* Hack */
  159 
  160         return copyout(&sysinfo, (caddr_t)args->info, sizeof(sysinfo));
  161 }
  162 #endif /*!__alpha__*/
  163 
  164 #ifndef __alpha__
  165 int
  166 linux_alarm(struct proc *p, struct linux_alarm_args *args)
  167 {
  168         struct itimerval it, old_it;
  169         struct timeval tv;
  170         int s;
  171 
  172 #ifdef DEBUG
  173         if (ldebug(alarm))
  174                 printf(ARGS(alarm, "%u"), args->secs);
  175 #endif
  176 
  177         if (args->secs > 100000000)
  178                 return EINVAL;
  179 
  180         it.it_value.tv_sec = (long)args->secs;
  181         it.it_value.tv_usec = 0;
  182         it.it_interval.tv_sec = 0;
  183         it.it_interval.tv_usec = 0;
  184         s = splsoftclock();
  185         old_it = p->p_realtimer;
  186         getmicrouptime(&tv);
  187         if (timevalisset(&old_it.it_value))
  188                 untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
  189         if (it.it_value.tv_sec != 0) {
  190                 p->p_ithandle = timeout(realitexpire, (caddr_t)p,
  191                     tvtohz(&it.it_value));
  192                 timevaladd(&it.it_value, &tv);
  193         }
  194         p->p_realtimer = it;
  195         splx(s);
  196         if (timevalcmp(&old_it.it_value, &tv, >)) {
  197                 timevalsub(&old_it.it_value, &tv);
  198                 if (old_it.it_value.tv_usec != 0)
  199                         old_it.it_value.tv_sec++;
  200                 p->p_retval[0] = old_it.it_value.tv_sec;
  201         }
  202         return 0;
  203 }
  204 #endif /*!__alpha__*/
  205 
  206 int
  207 linux_brk(struct proc *p, struct linux_brk_args *args)
  208 {
  209         struct vmspace *vm = p->p_vmspace;
  210         vm_offset_t new, old;
  211         struct obreak_args /* {
  212                 char * nsize;
  213         } */ tmp;
  214 
  215 #ifdef DEBUG
  216         if (ldebug(brk))
  217                 printf(ARGS(brk, "%p"), (void *)args->dsend);
  218 #endif
  219         old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
  220         new = (vm_offset_t)args->dsend;
  221         tmp.nsize = (char *) new;
  222         if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp))
  223                 p->p_retval[0] = (long)new;
  224         else
  225                 p->p_retval[0] = (long)old;
  226 
  227         return 0;
  228 }
  229 
  230 int
  231 linux_uselib(struct proc *p, struct linux_uselib_args *args)
  232 {
  233         struct nameidata ni;
  234         struct vnode *vp;
  235         struct exec *a_out;
  236         struct vattr attr;
  237         vm_offset_t vmaddr;
  238         unsigned long file_offset;
  239         vm_offset_t buffer;
  240         unsigned long bss_size;
  241         int error;
  242         caddr_t sg;
  243         int locked;
  244 
  245         sg = stackgap_init();
  246         CHECKALTEXIST(p, &sg, args->library);
  247 
  248 #ifdef DEBUG
  249         if (ldebug(uselib))
  250                 printf(ARGS(uselib, "%s"), args->library);
  251 #endif
  252 
  253         a_out = NULL;
  254         locked = 0;
  255         vp = NULL;
  256 
  257         NDINIT(&ni, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, args->library, p);
  258         error = namei(&ni);
  259         if (error)
  260                 goto cleanup;
  261 
  262         vp = ni.ni_vp;
  263         /*
  264          * XXX - This looks like a bogus check. A LOCKLEAF namei should not
  265          * succeed without returning a vnode.
  266          */
  267         if (vp == NULL) {
  268                 error = ENOEXEC;        /* ?? */
  269                 goto cleanup;
  270         }
  271         NDFREE(&ni, NDF_ONLY_PNBUF);
  272 
  273         /*
  274          * From here on down, we have a locked vnode that must be unlocked.
  275          */
  276         locked++;
  277 
  278         /* Writable? */
  279         if (vp->v_writecount) {
  280                 error = ETXTBSY;
  281                 goto cleanup;
  282         }
  283 
  284         /* Executable? */
  285         error = VOP_GETATTR(vp, &attr, p->p_ucred, p);
  286         if (error)
  287                 goto cleanup;
  288 
  289         if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
  290             ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) {
  291                 error = ENOEXEC;
  292                 goto cleanup;
  293         }
  294 
  295         /* Sensible size? */
  296         if (attr.va_size == 0) {
  297                 error = ENOEXEC;
  298                 goto cleanup;
  299         }
  300 
  301         /* Can we access it? */
  302         error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  303         if (error)
  304                 goto cleanup;
  305 
  306         error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
  307         if (error)
  308                 goto cleanup;
  309 
  310         /*
  311          * Lock no longer needed
  312          */
  313         VOP_UNLOCK(vp, 0, p);
  314         locked = 0;
  315 
  316         /* Pull in executable header into kernel_map */
  317         error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE,
  318             VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0);
  319         if (error)
  320                 goto cleanup;
  321 
  322         /* Is it a Linux binary ? */
  323         if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
  324                 error = ENOEXEC;
  325                 goto cleanup;
  326         }
  327 
  328         /*
  329          * While we are here, we should REALLY do some more checks
  330          */
  331 
  332         /* Set file/virtual offset based on a.out variant. */
  333         switch ((int)(a_out->a_magic & 0xffff)) {
  334         case 0413:      /* ZMAGIC */
  335                 file_offset = 1024;
  336                 break;
  337         case 0314:      /* QMAGIC */
  338                 file_offset = 0;
  339                 break;
  340         default:
  341                 error = ENOEXEC;
  342                 goto cleanup;
  343         }
  344 
  345         bss_size = round_page(a_out->a_bss);
  346 
  347         /* Check various fields in header for validity/bounds. */
  348         if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
  349                 error = ENOEXEC;
  350                 goto cleanup;
  351         }
  352 
  353         /* text + data can't exceed file size */
  354         if (a_out->a_data + a_out->a_text > attr.va_size) {
  355                 error = EFAULT;
  356                 goto cleanup;
  357         }
  358 
  359         /*
  360          * text/data/bss must not exceed limits
  361          * XXX - this is not complete. it should check current usage PLUS
  362          * the resources needed by this library.
  363          */
  364         if (a_out->a_text > maxtsiz ||
  365             a_out->a_data + bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) {
  366                 error = ENOMEM;
  367                 goto cleanup;
  368         }
  369 
  370         /* prevent more writers */
  371         vp->v_flag |= VTEXT;
  372 
  373         /*
  374          * Check if file_offset page aligned. Currently we cannot handle
  375          * misalinged file offsets, and so we read in the entire image
  376          * (what a waste).
  377          */
  378         if (file_offset & PAGE_MASK) {
  379 #ifdef DEBUG
  380                 printf("uselib: Non page aligned binary %lu\n", file_offset);
  381 #endif
  382                 /* Map text+data read/write/execute */
  383 
  384                 /* a_entry is the load address and is page aligned */
  385                 vmaddr = trunc_page(a_out->a_entry);
  386 
  387                 /* get anon user mapping, read+write+execute */
  388                 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0,
  389                     &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL,
  390                     VM_PROT_ALL, 0);
  391                 if (error)
  392                         goto cleanup;
  393 
  394                 /* map file into kernel_map */
  395                 error = vm_mmap(kernel_map, &buffer,
  396                     round_page(a_out->a_text + a_out->a_data + file_offset),
  397                     VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp,
  398                     trunc_page(file_offset));
  399                 if (error)
  400                         goto cleanup;
  401 
  402                 /* copy from kernel VM space to user space */
  403                 error = copyout((caddr_t)(uintptr_t)(buffer + file_offset),
  404                     (caddr_t)vmaddr, a_out->a_text + a_out->a_data);
  405 
  406                 /* release temporary kernel space */
  407                 vm_map_remove(kernel_map, buffer, buffer +
  408                     round_page(a_out->a_text + a_out->a_data + file_offset));
  409 
  410                 if (error)
  411                         goto cleanup;
  412         } else {
  413 #ifdef DEBUG
  414                 printf("uselib: Page aligned binary %lu\n", file_offset);
  415 #endif
  416                 /*
  417                  * for QMAGIC, a_entry is 20 bytes beyond the load address
  418                  * to skip the executable header
  419                  */
  420                 vmaddr = trunc_page(a_out->a_entry);
  421 
  422                 /*
  423                  * Map it all into the process's space as a single
  424                  * copy-on-write "data" segment.
  425                  */
  426                 error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
  427                     a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL,
  428                     MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset);
  429                 if (error)
  430                         goto cleanup;
  431         }
  432 #ifdef DEBUG
  433         printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0],
  434             ((long*)vmaddr)[1]);
  435 #endif
  436         if (bss_size != 0) {
  437                 /* Calculate BSS start address */
  438                 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text +
  439                     a_out->a_data;
  440 
  441                 /* allocate some 'anon' space */
  442                 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0,
  443                     &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
  444                 if (error)
  445                         goto cleanup;
  446         }
  447 
  448 cleanup:
  449         /* Unlock vnode if needed */
  450         if (locked)
  451                 VOP_UNLOCK(vp, 0, p);
  452 
  453         /* Release the kernel mapping. */
  454         if (a_out)
  455                 vm_map_remove(kernel_map, (vm_offset_t)a_out,
  456                     (vm_offset_t)a_out + PAGE_SIZE);
  457 
  458         return error;
  459 }
  460 
  461 int
  462 linux_select(struct proc *p, struct linux_select_args *args)
  463 {
  464         struct select_args bsa;
  465         struct timeval tv0, tv1, utv, *tvp;
  466         caddr_t sg;
  467         int error;
  468 
  469 #ifdef DEBUG
  470         if (ldebug(select))
  471                 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds,
  472                     (void *)args->readfds, (void *)args->writefds,
  473                     (void *)args->exceptfds, (void *)args->timeout);
  474 #endif
  475 
  476         error = 0;
  477         bsa.nd = args->nfds;
  478         bsa.in = args->readfds;
  479         bsa.ou = args->writefds;
  480         bsa.ex = args->exceptfds;
  481         bsa.tv = (struct timeval *)args->timeout;
  482 
  483         /*
  484          * Store current time for computation of the amount of
  485          * time left.
  486          */
  487         if (args->timeout) {
  488                 if ((error = copyin((caddr_t)args->timeout, &utv,
  489                     sizeof(utv))))
  490                         goto select_out;
  491 #ifdef DEBUG
  492                 if (ldebug(select))
  493                         printf(LMSG("incoming timeout (%ld/%ld)"),
  494                             utv.tv_sec, utv.tv_usec);
  495 #endif
  496 
  497                 if (itimerfix(&utv)) {
  498                         /*
  499                          * The timeval was invalid.  Convert it to something
  500                          * valid that will act as it does under Linux.
  501                          */
  502                         sg = stackgap_init();
  503                         tvp = stackgap_alloc(&sg, sizeof(utv));
  504                         utv.tv_sec += utv.tv_usec / 1000000;
  505                         utv.tv_usec %= 1000000;
  506                         if (utv.tv_usec < 0) {
  507                                 utv.tv_sec -= 1;
  508                                 utv.tv_usec += 1000000;
  509                         }
  510                         if (utv.tv_sec < 0)
  511                                 timevalclear(&utv);
  512                         if ((error = copyout(&utv, tvp, sizeof(utv))))
  513                                 goto select_out;
  514                         bsa.tv = tvp;
  515                 }
  516                 microtime(&tv0);
  517         }
  518 
  519         error = select(p, &bsa);
  520 #ifdef DEBUG
  521         if (ldebug(select))
  522                 printf(LMSG("real select returns %d"), error);
  523 #endif
  524         if (error) {
  525                 /*
  526                  * See fs/select.c in the Linux kernel.  Without this,
  527                  * Maelstrom doesn't work.
  528                  */
  529                 if (error == ERESTART)
  530                         error = EINTR;
  531                 goto select_out;
  532         }
  533 
  534         if (args->timeout) {
  535                 if (p->p_retval[0]) {
  536                         /*
  537                          * Compute how much time was left of the timeout,
  538                          * by subtracting the current time and the time
  539                          * before we started the call, and subtracting
  540                          * that result from the user-supplied value.
  541                          */
  542                         microtime(&tv1);
  543                         timevalsub(&tv1, &tv0);
  544                         timevalsub(&utv, &tv1);
  545                         if (utv.tv_sec < 0)
  546                                 timevalclear(&utv);
  547                 } else
  548                         timevalclear(&utv);
  549 #ifdef DEBUG
  550                 if (ldebug(select))
  551                         printf(LMSG("outgoing timeout (%ld/%ld)"),
  552                             utv.tv_sec, utv.tv_usec);
  553 #endif
  554                 if ((error = copyout(&utv, (caddr_t)args->timeout,
  555                     sizeof(utv))))
  556                         goto select_out;
  557         }
  558 
  559 select_out:
  560 #ifdef DEBUG
  561         if (ldebug(select))
  562                 printf(LMSG("select_out -> %d"), error);
  563 #endif
  564         return error;
  565 }
  566 
  567 int     
  568 linux_mremap(struct proc *p, struct linux_mremap_args *args)
  569 {
  570         struct munmap_args /* {
  571                 void *addr;
  572                 size_t len;
  573         } */ bsd_args; 
  574         int error = 0;
  575  
  576 #ifdef DEBUG
  577         if (ldebug(mremap))
  578                 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"),
  579                     (void *)args->addr, 
  580                     (unsigned long)args->old_len, 
  581                     (unsigned long)args->new_len,
  582                     (unsigned long)args->flags);
  583 #endif
  584         args->new_len = round_page(args->new_len);
  585         args->old_len = round_page(args->old_len);
  586 
  587         if (args->new_len > args->old_len) {
  588                 p->p_retval[0] = 0;
  589                 return ENOMEM;
  590         }
  591 
  592         if (args->new_len < args->old_len) {
  593                 bsd_args.addr = (caddr_t)(args->addr + args->new_len);
  594                 bsd_args.len = args->old_len - args->new_len;
  595                 error = munmap(p, &bsd_args);
  596         }
  597 
  598         p->p_retval[0] = error ? 0 : (u_long)args->addr;
  599         return error;
  600 }
  601 
  602 #define LINUX_MS_ASYNC          0x0001
  603 #define LINUX_MS_INVALIDATE     0x0002
  604 #define LINUX_MS_SYNC           0x0004
  605 
  606 int
  607 linux_msync(struct proc *p, struct linux_msync_args *args)
  608 {
  609         struct msync_args bsd_args;
  610 
  611         bsd_args.addr = (caddr_t)args->addr;
  612         bsd_args.len = args->len;
  613         bsd_args.flags = args->fl & ~LINUX_MS_SYNC;
  614 
  615         return msync(p, &bsd_args);
  616 }
  617 
  618 #ifndef __alpha__
  619 int
  620 linux_time(struct proc *p, struct linux_time_args *args)
  621 {
  622         struct timeval tv;
  623         l_time_t tm;
  624         int error;
  625 
  626 #ifdef DEBUG
  627         if (ldebug(time))
  628                 printf(ARGS(time, "*"));
  629 #endif
  630 
  631         microtime(&tv);
  632         tm = tv.tv_sec;
  633         if (args->tm && (error = copyout(&tm, (caddr_t)args->tm, sizeof(tm))))
  634                 return error;
  635         p->p_retval[0] = tm;
  636         return 0;
  637 }
  638 #endif  /*!__alpha__*/
  639 
  640 struct l_times_argv {
  641         l_long          tms_utime;
  642         l_long          tms_stime;
  643         l_long          tms_cutime;
  644         l_long          tms_cstime;
  645 };
  646 
  647 #ifdef __alpha__
  648 #define CLK_TCK 1024    /* Linux uses 1024 on alpha */
  649 #else
  650 #define CLK_TCK 100     /* Linux uses 100 */
  651 #endif
  652 
  653 #define CONVTCK(r)      (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
  654 
  655 int
  656 linux_times(struct proc *p, struct linux_times_args *args)
  657 {
  658         struct timeval tv;
  659         struct l_times_argv tms;
  660         struct rusage ru;
  661         int error;
  662 
  663 #ifdef DEBUG
  664         if (ldebug(times))
  665                 printf(ARGS(times, "*"));
  666 #endif
  667 
  668         calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
  669 
  670         tms.tms_utime = CONVTCK(ru.ru_utime);
  671         tms.tms_stime = CONVTCK(ru.ru_stime);
  672 
  673         tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
  674         tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
  675 
  676         if ((error = copyout(&tms, (caddr_t)args->buf, sizeof(tms))))
  677                 return error;
  678 
  679         microuptime(&tv);
  680         p->p_retval[0] = (int)CONVTCK(tv);
  681         return 0;
  682 }
  683 
  684 int
  685 linux_newuname(struct proc *p, struct linux_newuname_args *args)
  686 {
  687         struct l_new_utsname utsname;
  688         char *osrelease, *osname;
  689         int name[2];
  690         int error;
  691         size_t plen, olen;
  692 
  693 #ifdef DEBUG
  694         if (ldebug(newuname))
  695                 printf(ARGS(newuname, "*"));
  696 #endif
  697 
  698         osname = linux_get_osname(p);
  699         osrelease = linux_get_osrelease(p);
  700 
  701         bzero(&utsname, sizeof(utsname));
  702         strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1);
  703 
  704         name[0] = CTL_KERN;
  705         name[1] = KERN_HOSTNAME;
  706         olen = LINUX_MAX_UTSNAME-1;
  707         error = kernel_sysctl(p, name, 2, utsname.nodename, &olen, NULL, 0, &plen);
  708         if (error)
  709                 strncpy(utsname.nodename, hostname, LINUX_MAX_UTSNAME-1);
  710 
  711         strncpy(utsname.release, osrelease, LINUX_MAX_UTSNAME-1);
  712         strncpy(utsname.version, version, LINUX_MAX_UTSNAME-1);
  713         strncpy(utsname.machine, machine, LINUX_MAX_UTSNAME-1);
  714         strncpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME-1);
  715 
  716         return (copyout(&utsname, (caddr_t)args->buf, sizeof(utsname)));
  717 }
  718 
  719 #if defined(__i386__)
  720 struct l_utimbuf {
  721         l_time_t l_actime;
  722         l_time_t l_modtime;
  723 };
  724 
  725 int
  726 linux_utime(struct proc *p, struct linux_utime_args *args)
  727 {
  728         struct utimes_args /* {
  729                 char    *path;
  730                 struct  timeval *tptr;
  731         } */ bsdutimes;
  732         struct timeval tv[2], *tvp;
  733         struct l_utimbuf lut;
  734         int error;
  735         caddr_t sg;
  736 
  737         sg = stackgap_init();
  738         CHECKALTEXIST(p, &sg, args->fname);
  739 
  740 #ifdef DEBUG
  741         if (ldebug(utime))
  742                 printf(ARGS(utime, "%s, *"), args->fname);
  743 #endif
  744 
  745         if (args->times) {
  746                 if ((error = copyin((caddr_t)args->times, &lut, sizeof lut)))
  747                         return error;
  748                 tv[0].tv_sec = lut.l_actime;
  749                 tv[0].tv_usec = 0;
  750                 tv[1].tv_sec = lut.l_modtime;
  751                 tv[1].tv_usec = 0;
  752                 /* so that utimes can copyin */
  753                 tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv));
  754                 if (tvp == NULL)
  755                         return (ENAMETOOLONG);
  756                 if ((error = copyout(tv, tvp, sizeof(tv))))
  757                         return error;
  758                 bsdutimes.tptr = tvp;
  759         } else
  760                 bsdutimes.tptr = NULL;
  761 
  762         bsdutimes.path = args->fname;
  763         return utimes(p, &bsdutimes);
  764 }
  765 #endif /* __i386__ */
  766 
  767 #define __WCLONE 0x80000000
  768 
  769 #ifndef __alpha__
  770 int
  771 linux_waitpid(struct proc *p, struct linux_waitpid_args *args)
  772 {
  773         struct wait_args /* {
  774                 int pid;
  775                 int *status;
  776                 int options;
  777                 struct  rusage *rusage;
  778         } */ tmp;
  779         int error, tmpstat;
  780 
  781 #ifdef DEBUG
  782         if (ldebug(waitpid))
  783                 printf(ARGS(waitpid, "%d, %p, %d"),
  784                     args->pid, (void *)args->status, args->options);
  785 #endif
  786 
  787         tmp.pid = args->pid;
  788         tmp.status = args->status;
  789         tmp.options = (args->options & (WNOHANG | WUNTRACED));
  790         /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
  791         if (args->options & __WCLONE)
  792                 tmp.options |= WLINUXCLONE;
  793         tmp.rusage = NULL;
  794 
  795         if ((error = wait4(p, &tmp)) != 0)
  796                 return error;
  797 
  798         if (args->status) {
  799                 if ((error = copyin((caddr_t)args->status, &tmpstat,
  800                     sizeof(int))) != 0)
  801                         return error;
  802                 tmpstat &= 0xffff;
  803                 if (WIFSIGNALED(tmpstat))
  804                         tmpstat = (tmpstat & 0xffffff80) |
  805                             BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
  806                 else if (WIFSTOPPED(tmpstat))
  807                         tmpstat = (tmpstat & 0xffff00ff) |
  808                             (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
  809                 return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
  810         }
  811 
  812         return 0;
  813 }
  814 #endif  /*!__alpha__*/
  815 
  816 int
  817 linux_wait4(struct proc *p, struct linux_wait4_args *args)
  818 {
  819         struct wait_args /* {
  820                 int pid;
  821                 int *status;
  822                 int options;
  823                 struct  rusage *rusage;
  824         } */ tmp;
  825         int error, tmpstat;
  826 
  827 #ifdef DEBUG
  828         if (ldebug(wait4))
  829                 printf(ARGS(wait4, "%d, %p, %d, %p"),
  830                     args->pid, (void *)args->status, args->options,
  831                     (void *)args->rusage);
  832 #endif
  833 
  834         tmp.pid = args->pid;
  835         tmp.status = args->status;
  836         tmp.options = (args->options & (WNOHANG | WUNTRACED));
  837         /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
  838         if (args->options & __WCLONE)
  839                 tmp.options |= WLINUXCLONE;
  840         tmp.rusage = (struct rusage *)args->rusage;
  841 
  842         if ((error = wait4(p, &tmp)) != 0)
  843                 return error;
  844 
  845         SIGDELSET(p->p_siglist, SIGCHLD);
  846 
  847         if (args->status) {
  848                 if ((error = copyin((caddr_t)args->status, &tmpstat,
  849                     sizeof(int))) != 0)
  850                         return error;
  851                 tmpstat &= 0xffff;
  852                 if (WIFSIGNALED(tmpstat))
  853                         tmpstat = (tmpstat & 0xffffff80) |
  854                             BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
  855                 else if (WIFSTOPPED(tmpstat))
  856                         tmpstat = (tmpstat & 0xffff00ff) |
  857                             (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
  858                 return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
  859         }
  860 
  861         return 0;
  862 }
  863 
  864 int
  865 linux_mknod(struct proc *p, struct linux_mknod_args *args)
  866 {
  867         caddr_t sg;
  868         struct mknod_args bsd_mknod;
  869         struct mkfifo_args bsd_mkfifo;
  870 
  871         sg = stackgap_init();
  872 
  873         CHECKALTCREAT(p, &sg, args->path);
  874 
  875 #ifdef DEBUG
  876         if (ldebug(mknod))
  877                 printf(ARGS(mknod, "%s, %d, %d"),
  878                     args->path, args->mode, args->dev);
  879 #endif
  880 
  881         if (args->mode & S_IFIFO) {
  882                 bsd_mkfifo.path = args->path;
  883                 bsd_mkfifo.mode = args->mode;
  884                 return mkfifo(p, &bsd_mkfifo);
  885         } else {
  886                 bsd_mknod.path = args->path;
  887                 bsd_mknod.mode = args->mode;
  888                 bsd_mknod.dev = args->dev;
  889                 return mknod(p, &bsd_mknod);
  890         }
  891 }
  892 
  893 /*
  894  * UGH! This is just about the dumbest idea I've ever heard!!
  895  */
  896 int
  897 linux_personality(struct proc *p, struct linux_personality_args *args)
  898 {
  899 #ifdef DEBUG
  900         if (ldebug(personality))
  901                 printf(ARGS(personality, "%d"), args->per);
  902 #endif
  903 #ifndef __alpha__
  904         if (args->per != 0)
  905                 return EINVAL;
  906 #endif
  907 
  908         /* Yes Jim, it's still a Linux... */
  909         p->p_retval[0] = 0;
  910         return 0;
  911 }
  912 
  913 /*
  914  * Wrappers for get/setitimer for debugging..
  915  */
  916 int
  917 linux_setitimer(struct proc *p, struct linux_setitimer_args *args)
  918 {
  919         struct setitimer_args bsa;
  920         struct itimerval foo;
  921         int error;
  922 
  923 #ifdef DEBUG
  924         if (ldebug(setitimer))
  925                 printf(ARGS(setitimer, "%p, %p"),
  926                     (void *)args->itv, (void *)args->oitv);
  927 #endif
  928         bsa.which = args->which;
  929         bsa.itv = (struct itimerval *)args->itv;
  930         bsa.oitv = (struct itimerval *)args->oitv;
  931         if (args->itv) {
  932             if ((error = copyin((caddr_t)args->itv, &foo, sizeof(foo))))
  933                 return error;
  934 #ifdef DEBUG
  935             if (ldebug(setitimer)) {
  936                 printf("setitimer: value: sec: %ld, usec: %ld\n",
  937                     foo.it_value.tv_sec, foo.it_value.tv_usec);
  938                 printf("setitimer: interval: sec: %ld, usec: %ld\n",
  939                     foo.it_interval.tv_sec, foo.it_interval.tv_usec);
  940             }
  941 #endif
  942         }
  943         return setitimer(p, &bsa);
  944 }
  945 
  946 int
  947 linux_getitimer(struct proc *p, struct linux_getitimer_args *args)
  948 {
  949         struct getitimer_args bsa;
  950 #ifdef DEBUG
  951         if (ldebug(getitimer))
  952                 printf(ARGS(getitimer, "%p"), (void *)args->itv);
  953 #endif
  954         bsa.which = args->which;
  955         bsa.itv = (struct itimerval *)args->itv;
  956         return getitimer(p, &bsa);
  957 }
  958 
  959 #ifndef __alpha__
  960 int
  961 linux_nice(struct proc *p, struct linux_nice_args *args)
  962 {
  963         struct setpriority_args bsd_args;
  964 
  965         bsd_args.which = PRIO_PROCESS;
  966         bsd_args.who = 0;       /* current process */
  967         bsd_args.prio = args->inc;
  968         return setpriority(p, &bsd_args);
  969 }
  970 #endif  /*!__alpha__*/
  971 
  972 int
  973 linux_setgroups(struct proc *p, struct linux_setgroups_args *args)
  974 {
  975         struct ucred *newcred, *oldcred;
  976         l_gid_t linux_gidset[NGROUPS];
  977         gid_t *bsd_gidset;
  978         int ngrp, error;
  979 
  980         ngrp = args->gidsetsize;
  981         oldcred = p->p_ucred;
  982 
  983         /*
  984          * cr_groups[0] holds egid. Setting the whole set from
  985          * the supplied set will cause egid to be changed too.
  986          * Keep cr_groups[0] unchanged to prevent that.
  987          */
  988 
  989         if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
  990                 return (error);
  991 
  992         if (ngrp < 0 || ngrp >= NGROUPS)
  993                 return (EINVAL);
  994 
  995         newcred = crdup(oldcred);
  996         if (ngrp > 0) {
  997                 error = copyin((caddr_t)args->grouplist, linux_gidset,
  998                                ngrp * sizeof(l_gid_t));
  999                 if (error)
 1000                         return (error);
 1001 
 1002                 newcred->cr_ngroups = ngrp + 1;
 1003 
 1004                 bsd_gidset = newcred->cr_groups;
 1005                 ngrp--;
 1006                 while (ngrp >= 0) {
 1007                         bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
 1008                         ngrp--;
 1009                 }
 1010         }
 1011         else
 1012                 newcred->cr_ngroups = 1;
 1013 
 1014         setsugid(p);
 1015         p->p_ucred = newcred;
 1016         crfree(oldcred);
 1017         return (0);
 1018 }
 1019 
 1020 int
 1021 linux_getgroups(struct proc *p, struct linux_getgroups_args *args)
 1022 {
 1023         struct ucred *cred;
 1024         l_gid_t linux_gidset[NGROUPS];
 1025         gid_t *bsd_gidset;
 1026         int bsd_gidsetsz, ngrp, error;
 1027 
 1028         cred = p->p_ucred;
 1029         bsd_gidset = cred->cr_groups;
 1030         bsd_gidsetsz = cred->cr_ngroups - 1;
 1031 
 1032         /*
 1033          * cr_groups[0] holds egid. Returning the whole set
 1034          * here will cause a duplicate. Exclude cr_groups[0]
 1035          * to prevent that.
 1036          */
 1037 
 1038         if ((ngrp = args->gidsetsize) == 0) {
 1039                 p->p_retval[0] = bsd_gidsetsz;
 1040                 return (0);
 1041         }
 1042 
 1043         if (ngrp < bsd_gidsetsz)
 1044                 return (EINVAL);
 1045 
 1046         ngrp = 0;
 1047         while (ngrp < bsd_gidsetsz) {
 1048                 linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
 1049                 ngrp++;
 1050         }
 1051 
 1052         if ((error = copyout(linux_gidset, (caddr_t)args->grouplist,
 1053             ngrp * sizeof(l_gid_t))))
 1054                 return (error);
 1055 
 1056         p->p_retval[0] = ngrp;
 1057         return (0);
 1058 }
 1059 
 1060 #ifndef __alpha__
 1061 int
 1062 linux_setrlimit(struct proc *p, struct linux_setrlimit_args *args)
 1063 {
 1064         struct __setrlimit_args bsd;
 1065         struct l_rlimit rlim;
 1066         int error;
 1067         caddr_t sg = stackgap_init();
 1068 
 1069 #ifdef DEBUG
 1070         if (ldebug(setrlimit))
 1071                 printf(ARGS(setrlimit, "%d, %p"),
 1072                     args->resource, (void *)args->rlim);
 1073 #endif
 1074 
 1075         if (args->resource >= LINUX_RLIM_NLIMITS)
 1076                 return (EINVAL);
 1077 
 1078         bsd.which = linux_to_bsd_resource[args->resource];
 1079         if (bsd.which == -1)
 1080                 return (EINVAL);
 1081 
 1082         error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim));
 1083         if (error)
 1084                 return (error);
 1085 
 1086         bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
 1087         bsd.rlp->rlim_cur = (rlim_t)rlim.rlim_cur;
 1088         bsd.rlp->rlim_max = (rlim_t)rlim.rlim_max;
 1089         return (setrlimit(p, &bsd));
 1090 }
 1091 
 1092 int
 1093 linux_old_getrlimit(struct proc *p, struct linux_old_getrlimit_args *args)
 1094 {
 1095         struct __getrlimit_args bsd;
 1096         struct l_rlimit rlim;
 1097         int error;
 1098         caddr_t sg = stackgap_init();
 1099 
 1100 #ifdef DEBUG
 1101         if (ldebug(old_getrlimit))
 1102                 printf(ARGS(old_getrlimit, "%d, %p"),
 1103                     args->resource, (void *)args->rlim);
 1104 #endif
 1105 
 1106         if (args->resource >= LINUX_RLIM_NLIMITS)
 1107                 return (EINVAL);
 1108 
 1109         bsd.which = linux_to_bsd_resource[args->resource];
 1110         if (bsd.which == -1)
 1111                 return (EINVAL);
 1112 
 1113         bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
 1114         error = getrlimit(p, &bsd);
 1115         if (error)
 1116                 return (error);
 1117 
 1118         rlim.rlim_cur = (unsigned long)bsd.rlp->rlim_cur;
 1119         if (rlim.rlim_cur == ULONG_MAX)
 1120                 rlim.rlim_cur = LONG_MAX;
 1121         rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max;
 1122         if (rlim.rlim_max == ULONG_MAX)
 1123                 rlim.rlim_max = LONG_MAX;
 1124         return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
 1125 }
 1126 
 1127 int
 1128 linux_getrlimit(struct proc *p, struct linux_getrlimit_args *args)
 1129 {
 1130         struct __getrlimit_args bsd;
 1131         struct l_rlimit rlim;
 1132         int error;
 1133         caddr_t sg = stackgap_init();
 1134 
 1135 #ifdef DEBUG
 1136         if (ldebug(getrlimit))
 1137                 printf(ARGS(getrlimit, "%d, %p"),
 1138                     args->resource, (void *)args->rlim);
 1139 #endif
 1140 
 1141         if (args->resource >= LINUX_RLIM_NLIMITS)
 1142                 return (EINVAL);
 1143 
 1144         bsd.which = linux_to_bsd_resource[args->resource];
 1145         if (bsd.which == -1)
 1146                 return (EINVAL);
 1147 
 1148         bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
 1149         error = getrlimit(p, &bsd);
 1150         if (error)
 1151                 return (error);
 1152 
 1153         rlim.rlim_cur = (l_ulong)bsd.rlp->rlim_cur;
 1154         rlim.rlim_max = (l_ulong)bsd.rlp->rlim_max;
 1155         return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
 1156 }
 1157 #endif /*!__alpha__*/
 1158 
 1159 int
 1160 linux_sched_setscheduler(struct proc *p,
 1161     struct linux_sched_setscheduler_args *args)
 1162 {
 1163         struct sched_setscheduler_args bsd;
 1164 
 1165 #ifdef DEBUG
 1166         if (ldebug(sched_setscheduler))
 1167                 printf(ARGS(sched_setscheduler, "%d, %d, %p"),
 1168                     args->pid, args->policy, (const void *)args->param);
 1169 #endif
 1170 
 1171         switch (args->policy) {
 1172         case LINUX_SCHED_OTHER:
 1173                 bsd.policy = SCHED_OTHER;
 1174                 break;
 1175         case LINUX_SCHED_FIFO:
 1176                 bsd.policy = SCHED_FIFO;
 1177                 break;
 1178         case LINUX_SCHED_RR:
 1179                 bsd.policy = SCHED_RR;
 1180                 break;
 1181         default:
 1182                 return EINVAL;
 1183         }
 1184 
 1185         bsd.pid = args->pid;
 1186         bsd.param = (struct sched_param *)args->param;
 1187         return sched_setscheduler(p, &bsd);
 1188 }
 1189 
 1190 int
 1191 linux_sched_getscheduler(struct proc *p,
 1192     struct linux_sched_getscheduler_args *args)
 1193 {
 1194         struct sched_getscheduler_args bsd;
 1195         int error;
 1196 
 1197 #ifdef DEBUG
 1198         if (ldebug(sched_getscheduler))
 1199                 printf(ARGS(sched_getscheduler, "%d"), args->pid);
 1200 #endif
 1201 
 1202         bsd.pid = args->pid;
 1203         error = sched_getscheduler(p, &bsd);
 1204 
 1205         switch (p->p_retval[0]) {
 1206         case SCHED_OTHER:
 1207                 p->p_retval[0] = LINUX_SCHED_OTHER;
 1208                 break;
 1209         case SCHED_FIFO:
 1210                 p->p_retval[0] = LINUX_SCHED_FIFO;
 1211                 break;
 1212         case SCHED_RR:
 1213                 p->p_retval[0] = LINUX_SCHED_RR;
 1214                 break;
 1215         }
 1216 
 1217         return error;
 1218 }
 1219 
 1220 int
 1221 linux_sched_get_priority_max(struct proc *p,
 1222     struct linux_sched_get_priority_max_args *args)
 1223 {
 1224         struct sched_get_priority_max_args bsd;
 1225 
 1226 #ifdef DEBUG
 1227         if (ldebug(sched_get_priority_max))
 1228                 printf(ARGS(sched_get_priority_max, "%d"), args->policy);
 1229 #endif
 1230 
 1231         switch (args->policy) {
 1232         case LINUX_SCHED_OTHER:
 1233                 bsd.policy = SCHED_OTHER;
 1234                 break;
 1235         case LINUX_SCHED_FIFO:
 1236                 bsd.policy = SCHED_FIFO;
 1237                 break;
 1238         case LINUX_SCHED_RR:
 1239                 bsd.policy = SCHED_RR;
 1240                 break;
 1241         default:
 1242                 return EINVAL;
 1243         }
 1244         return sched_get_priority_max(p, &bsd);
 1245 }
 1246 
 1247 int
 1248 linux_sched_get_priority_min(struct proc *p,
 1249     struct linux_sched_get_priority_min_args *args)
 1250 {
 1251         struct sched_get_priority_min_args bsd;
 1252 
 1253 #ifdef DEBUG
 1254         if (ldebug(sched_get_priority_min))
 1255                 printf(ARGS(sched_get_priority_min, "%d"), args->policy);
 1256 #endif
 1257 
 1258         switch (args->policy) {
 1259         case LINUX_SCHED_OTHER:
 1260                 bsd.policy = SCHED_OTHER;
 1261                 break;
 1262         case LINUX_SCHED_FIFO:
 1263                 bsd.policy = SCHED_FIFO;
 1264                 break;
 1265         case LINUX_SCHED_RR:
 1266                 bsd.policy = SCHED_RR;
 1267                 break;
 1268         default:
 1269                 return EINVAL;
 1270         }
 1271         return sched_get_priority_min(p, &bsd);
 1272 }
 1273 
 1274 #define REBOOT_CAD_ON   0x89abcdef
 1275 #define REBOOT_CAD_OFF  0
 1276 #define REBOOT_HALT     0xcdef0123
 1277 
 1278 int
 1279 linux_reboot(struct proc *p, struct linux_reboot_args *args)
 1280 {
 1281         struct reboot_args bsd_args;
 1282 
 1283 #ifdef DEBUG
 1284         if (ldebug(reboot))
 1285                 printf(ARGS(reboot, "0x%x"), args->cmd);
 1286 #endif
 1287         if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF)
 1288                 return (0);
 1289         bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0;
 1290         return (reboot(p, &bsd_args));
 1291 }
 1292 
 1293 #ifndef __alpha__
 1294 
 1295 /*
 1296  * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify
 1297  * p->p_retval[1] when COMPAT_43 or COMPAT_SUNOS is defined. This
 1298  * globbers registers that are assumed to be preserved. The following
 1299  * lightweight syscalls fixes this. See also linux_getgid16() and
 1300  * linux_getuid16() in linux_uid16.c.
 1301  *
 1302  * linux_getpid() - MP SAFE
 1303  * linux_getgid() - MP SAFE
 1304  * linux_getuid() - MP SAFE
 1305  */
 1306 
 1307 int
 1308 linux_getpid(struct proc *p, struct linux_getpid_args *args)
 1309 {
 1310 
 1311         p->p_retval[0] = p->p_pid;
 1312         return (0);
 1313 }
 1314 
 1315 int
 1316 linux_getgid(struct proc *p, struct linux_getgid_args *args)
 1317 {
 1318 
 1319         p->p_retval[0] = p->p_cred->p_rgid;
 1320         return (0);
 1321 }
 1322 
 1323 int
 1324 linux_getuid(struct proc *p, struct linux_getuid_args *args)
 1325 {
 1326 
 1327         p->p_retval[0] = p->p_cred->p_ruid;
 1328         return (0);
 1329 }
 1330 
 1331 #endif /*!__alpha__*/
 1332 
 1333 int
 1334 linux_getsid(struct proc *p, struct linux_getsid_args *args)
 1335 {
 1336         struct getsid_args bsd;
 1337         bsd.pid = args->pid;
 1338         return getsid(p, &bsd);
 1339 }

Cache object: c27b182ae9ab23ac9416380f94bf60ab


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