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

Cache object: 617a2b8f874bc1407243d50d9b752491


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