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


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

FreeBSD/Linux Kernel Cross Reference
sys/i386/linux/linux_machdep.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) 2000 Marcel Moolenaar
    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  * $FreeBSD: releng/5.1/sys/i386/linux/linux_machdep.c 113689 2003-04-18 20:54:41Z jhb $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/lock.h>
   34 #include <sys/mman.h>
   35 #include <sys/mutex.h>
   36 #include <sys/proc.h>
   37 #include <sys/resource.h>
   38 #include <sys/resourcevar.h>
   39 #include <sys/syscallsubr.h>
   40 #include <sys/sysproto.h>
   41 #include <sys/unistd.h>
   42 
   43 #include <machine/frame.h>
   44 #include <machine/psl.h>
   45 #include <machine/segments.h>
   46 #include <machine/sysarch.h>
   47 
   48 #include <vm/vm.h>
   49 #include <vm/pmap.h>
   50 #include <vm/vm_map.h>
   51 
   52 #include <i386/linux/linux.h>
   53 #include <i386/linux/linux_proto.h>
   54 #include <compat/linux/linux_ipc.h>
   55 #include <compat/linux/linux_signal.h>
   56 #include <compat/linux/linux_util.h>
   57 
   58 struct l_descriptor {
   59         l_uint          entry_number;
   60         l_ulong         base_addr;
   61         l_uint          limit;
   62         l_uint          seg_32bit:1;
   63         l_uint          contents:2;
   64         l_uint          read_exec_only:1;
   65         l_uint          limit_in_pages:1;
   66         l_uint          seg_not_present:1;
   67         l_uint          useable:1;
   68 };
   69 
   70 struct l_old_select_argv {
   71         l_int           nfds;
   72         l_fd_set        *readfds;
   73         l_fd_set        *writefds;
   74         l_fd_set        *exceptfds;
   75         struct l_timeval        *timeout;
   76 };
   77 
   78 int
   79 linux_to_bsd_sigaltstack(int lsa)
   80 {
   81         int bsa = 0;
   82 
   83         if (lsa & LINUX_SS_DISABLE)
   84                 bsa |= SS_DISABLE;
   85         if (lsa & LINUX_SS_ONSTACK)
   86                 bsa |= SS_ONSTACK;
   87         return (bsa);
   88 }
   89 
   90 int
   91 bsd_to_linux_sigaltstack(int bsa)
   92 {
   93         int lsa = 0;
   94 
   95         if (bsa & SS_DISABLE)
   96                 lsa |= LINUX_SS_DISABLE;
   97         if (bsa & SS_ONSTACK)
   98                 lsa |= LINUX_SS_ONSTACK;
   99         return (lsa);
  100 }
  101 
  102 int
  103 linux_execve(struct thread *td, struct linux_execve_args *args)
  104 {
  105         struct execve_args bsd;
  106         caddr_t sg;
  107 
  108         sg = stackgap_init();
  109         CHECKALTEXIST(td, &sg, args->path);
  110 
  111 #ifdef DEBUG
  112         if (ldebug(execve))
  113                 printf(ARGS(execve, "%s"), args->path);
  114 #endif
  115 
  116         bsd.fname = args->path;
  117         bsd.argv = args->argp;
  118         bsd.envv = args->envp;
  119         return (execve(td, &bsd));
  120 }
  121 
  122 struct l_ipc_kludge {
  123         struct l_msgbuf *msgp;
  124         l_long msgtyp;
  125 };
  126 
  127 int
  128 linux_ipc(struct thread *td, struct linux_ipc_args *args)
  129 {
  130 
  131         switch (args->what & 0xFFFF) {
  132         case LINUX_SEMOP: {
  133                 struct linux_semop_args a;
  134 
  135                 a.semid = args->arg1;
  136                 a.tsops = args->ptr;
  137                 a.nsops = args->arg2;
  138                 return (linux_semop(td, &a));
  139         }
  140         case LINUX_SEMGET: {
  141                 struct linux_semget_args a;
  142 
  143                 a.key = args->arg1;
  144                 a.nsems = args->arg2;
  145                 a.semflg = args->arg3;
  146                 return (linux_semget(td, &a));
  147         }
  148         case LINUX_SEMCTL: {
  149                 struct linux_semctl_args a;
  150                 int error;
  151 
  152                 a.semid = args->arg1;
  153                 a.semnum = args->arg2;
  154                 a.cmd = args->arg3;
  155                 error = copyin(args->ptr, &a.arg, sizeof(a.arg));
  156                 if (error)
  157                         return (error);
  158                 return (linux_semctl(td, &a));
  159         }
  160         case LINUX_MSGSND: {
  161                 struct linux_msgsnd_args a;
  162 
  163                 a.msqid = args->arg1;
  164                 a.msgp = args->ptr;
  165                 a.msgsz = args->arg2;
  166                 a.msgflg = args->arg3;
  167                 return (linux_msgsnd(td, &a));
  168         }
  169         case LINUX_MSGRCV: {
  170                 struct linux_msgrcv_args a;
  171 
  172                 a.msqid = args->arg1;
  173                 a.msgsz = args->arg2;
  174                 a.msgflg = args->arg3;
  175                 if ((args->what >> 16) == 0) {
  176                         struct l_ipc_kludge tmp;
  177                         int error;
  178 
  179                         if (args->ptr == NULL)
  180                                 return (EINVAL);
  181                         error = copyin(args->ptr, &tmp, sizeof(tmp));
  182                         if (error)
  183                                 return (error);
  184                         a.msgp = tmp.msgp;
  185                         a.msgtyp = tmp.msgtyp;
  186                 } else {
  187                         a.msgp = args->ptr;
  188                         a.msgtyp = args->arg5;
  189                 }
  190                 return (linux_msgrcv(td, &a));
  191         }
  192         case LINUX_MSGGET: {
  193                 struct linux_msgget_args a;
  194 
  195                 a.key = args->arg1;
  196                 a.msgflg = args->arg2;
  197                 return (linux_msgget(td, &a));
  198         }
  199         case LINUX_MSGCTL: {
  200                 struct linux_msgctl_args a;
  201 
  202                 a.msqid = args->arg1;
  203                 a.cmd = args->arg2;
  204                 a.buf = args->ptr;
  205                 return (linux_msgctl(td, &a));
  206         }
  207         case LINUX_SHMAT: {
  208                 struct linux_shmat_args a;
  209 
  210                 a.shmid = args->arg1;
  211                 a.shmaddr = args->ptr;
  212                 a.shmflg = args->arg2;
  213                 a.raddr = (l_ulong *)args->arg3;
  214                 return (linux_shmat(td, &a));
  215         }
  216         case LINUX_SHMDT: {
  217                 struct linux_shmdt_args a;
  218 
  219                 a.shmaddr = args->ptr;
  220                 return (linux_shmdt(td, &a));
  221         }
  222         case LINUX_SHMGET: {
  223                 struct linux_shmget_args a;
  224 
  225                 a.key = args->arg1;
  226                 a.size = args->arg2;
  227                 a.shmflg = args->arg3;
  228                 return (linux_shmget(td, &a));
  229         }
  230         case LINUX_SHMCTL: {
  231                 struct linux_shmctl_args a;
  232 
  233                 a.shmid = args->arg1;
  234                 a.cmd = args->arg2;
  235                 a.buf = args->ptr;
  236                 return (linux_shmctl(td, &a));
  237         }
  238         default:
  239                 break;
  240         }
  241 
  242         return (EINVAL);
  243 }
  244 
  245 int
  246 linux_old_select(struct thread *td, struct linux_old_select_args *args)
  247 {
  248         struct l_old_select_argv linux_args;
  249         struct linux_select_args newsel;
  250         int error;
  251 
  252 #ifdef DEBUG
  253         if (ldebug(old_select))
  254                 printf(ARGS(old_select, "%p"), args->ptr);
  255 #endif
  256 
  257         error = copyin(args->ptr, &linux_args, sizeof(linux_args));
  258         if (error)
  259                 return (error);
  260 
  261         newsel.nfds = linux_args.nfds;
  262         newsel.readfds = linux_args.readfds;
  263         newsel.writefds = linux_args.writefds;
  264         newsel.exceptfds = linux_args.exceptfds;
  265         newsel.timeout = linux_args.timeout;
  266         return (linux_select(td, &newsel));
  267 }
  268 
  269 int
  270 linux_fork(struct thread *td, struct linux_fork_args *args)
  271 {
  272         int error;
  273 
  274 #ifdef DEBUG
  275         if (ldebug(fork))
  276                 printf(ARGS(fork, ""));
  277 #endif
  278 
  279         if ((error = fork(td, (struct fork_args *)args)) != 0)
  280                 return (error);
  281 
  282         if (td->td_retval[1] == 1)
  283                 td->td_retval[0] = 0;
  284         return (0);
  285 }
  286 
  287 int
  288 linux_vfork(struct thread *td, struct linux_vfork_args *args)
  289 {
  290         int error;
  291 
  292 #ifdef DEBUG
  293         if (ldebug(vfork))
  294                 printf(ARGS(vfork, ""));
  295 #endif
  296 
  297         if ((error = vfork(td, (struct vfork_args *)args)) != 0)
  298                 return (error);
  299         /* Are we the child? */
  300         if (td->td_retval[1] == 1)
  301                 td->td_retval[0] = 0;
  302         return (0);
  303 }
  304 
  305 #define CLONE_VM        0x100
  306 #define CLONE_FS        0x200
  307 #define CLONE_FILES     0x400
  308 #define CLONE_SIGHAND   0x800
  309 #define CLONE_PID       0x1000
  310 
  311 int
  312 linux_clone(struct thread *td, struct linux_clone_args *args)
  313 {
  314         int error, ff = RFPROC | RFSTOPPED;
  315         struct proc *p2;
  316         struct thread *td2;
  317         int exit_signal;
  318 
  319 #ifdef DEBUG
  320         if (ldebug(clone)) {
  321                 printf(ARGS(clone, "flags %x, stack %x"),
  322                     (unsigned int)args->flags, (unsigned int)args->stack);
  323                 if (args->flags & CLONE_PID)
  324                         printf(LMSG("CLONE_PID not yet supported"));
  325         }
  326 #endif
  327 
  328         if (!args->stack)
  329                 return (EINVAL);
  330 
  331         exit_signal = args->flags & 0x000000ff;
  332         if (exit_signal >= LINUX_NSIG)
  333                 return (EINVAL);
  334 
  335         if (exit_signal <= LINUX_SIGTBLSZ)
  336                 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)];
  337 
  338         if (args->flags & CLONE_VM)
  339                 ff |= RFMEM;
  340         if (args->flags & CLONE_SIGHAND)
  341                 ff |= RFSIGSHARE;
  342         if (!(args->flags & CLONE_FILES))
  343                 ff |= RFFDG;
  344 
  345         error = fork1(td, ff, 0, &p2);
  346         if (error)
  347                 return (error);
  348         
  349 
  350         PROC_LOCK(p2);
  351         p2->p_sigparent = exit_signal;
  352         PROC_UNLOCK(p2);
  353         td2 = FIRST_THREAD_IN_PROC(p2);
  354         td2->td_frame->tf_esp = (unsigned int)args->stack;
  355 
  356 #ifdef DEBUG
  357         if (ldebug(clone))
  358                 printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
  359                     (long)p2->p_pid, args->stack, exit_signal);
  360 #endif
  361 
  362         /*
  363          * Make this runnable after we are finished with it.
  364          */
  365         mtx_lock_spin(&sched_lock);
  366         TD_SET_CAN_RUN(td2);
  367         setrunqueue(td2);
  368         mtx_unlock_spin(&sched_lock);
  369 
  370         td->td_retval[0] = p2->p_pid;
  371         td->td_retval[1] = 0;
  372         return (0);
  373 }
  374 
  375 /* XXX move */
  376 struct l_mmap_argv {
  377         l_caddr_t       addr;
  378         l_int           len;
  379         l_int           prot;
  380         l_int           flags;
  381         l_int           fd;
  382         l_int           pos;
  383 };
  384 
  385 #define STACK_SIZE  (2 * 1024 * 1024)
  386 #define GUARD_SIZE  (4 * PAGE_SIZE)
  387 
  388 static int linux_mmap_common(struct thread *, struct l_mmap_argv *);
  389 
  390 int
  391 linux_mmap2(struct thread *td, struct linux_mmap2_args *args)
  392 {
  393         struct l_mmap_argv linux_args;
  394 
  395 #ifdef DEBUG
  396         if (ldebug(mmap2))
  397                 printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
  398                     (void *)args->addr, args->len, args->prot,
  399                     args->flags, args->fd, args->pgoff);
  400 #endif
  401 
  402         linux_args.addr = (l_caddr_t)args->addr;
  403         linux_args.len = args->len;
  404         linux_args.prot = args->prot;
  405         linux_args.flags = args->flags;
  406         linux_args.fd = args->fd;
  407         linux_args.pos = args->pgoff * PAGE_SIZE;
  408 
  409         return (linux_mmap_common(td, &linux_args));
  410 }
  411 
  412 int
  413 linux_mmap(struct thread *td, struct linux_mmap_args *args)
  414 {
  415         int error;
  416         struct l_mmap_argv linux_args;
  417 
  418         error = copyin(args->ptr, &linux_args, sizeof(linux_args));
  419         if (error)
  420                 return (error);
  421 
  422 #ifdef DEBUG
  423         if (ldebug(mmap))
  424                 printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"),
  425                     (void *)linux_args.addr, linux_args.len, linux_args.prot,
  426                     linux_args.flags, linux_args.fd, linux_args.pos);
  427 #endif
  428 
  429         return (linux_mmap_common(td, &linux_args));
  430 }
  431 
  432 static int
  433 linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
  434 {
  435         struct proc *p = td->td_proc;
  436         struct mmap_args /* {
  437                 caddr_t addr;
  438                 size_t len;
  439                 int prot;
  440                 int flags;
  441                 int fd;
  442                 long pad;
  443                 off_t pos;
  444         } */ bsd_args;
  445         int error;
  446 
  447         error = 0;
  448         bsd_args.flags = 0;
  449         if (linux_args->flags & LINUX_MAP_SHARED)
  450                 bsd_args.flags |= MAP_SHARED;
  451         if (linux_args->flags & LINUX_MAP_PRIVATE)
  452                 bsd_args.flags |= MAP_PRIVATE;
  453         if (linux_args->flags & LINUX_MAP_FIXED)
  454                 bsd_args.flags |= MAP_FIXED;
  455         if (linux_args->flags & LINUX_MAP_ANON)
  456                 bsd_args.flags |= MAP_ANON;
  457         else
  458                 bsd_args.flags |= MAP_NOSYNC;
  459         if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
  460                 bsd_args.flags |= MAP_STACK;
  461 
  462                 /* The linux MAP_GROWSDOWN option does not limit auto
  463                  * growth of the region.  Linux mmap with this option
  464                  * takes as addr the inital BOS, and as len, the initial
  465                  * region size.  It can then grow down from addr without
  466                  * limit.  However, linux threads has an implicit internal
  467                  * limit to stack size of STACK_SIZE.  Its just not
  468                  * enforced explicitly in linux.  But, here we impose
  469                  * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
  470                  * region, since we can do this with our mmap.
  471                  *
  472                  * Our mmap with MAP_STACK takes addr as the maximum
  473                  * downsize limit on BOS, and as len the max size of
  474                  * the region.  It them maps the top SGROWSIZ bytes,
  475                  * and autgrows the region down, up to the limit
  476                  * in addr.
  477                  *
  478                  * If we don't use the MAP_STACK option, the effect
  479                  * of this code is to allocate a stack region of a
  480                  * fixed size of (STACK_SIZE - GUARD_SIZE).
  481                  */
  482 
  483                 /* This gives us TOS */
  484                 bsd_args.addr = linux_args->addr + linux_args->len;
  485 
  486                 if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
  487                         /* Some linux apps will attempt to mmap
  488                          * thread stacks near the top of their
  489                          * address space.  If their TOS is greater
  490                          * than vm_maxsaddr, vm_map_growstack()
  491                          * will confuse the thread stack with the
  492                          * process stack and deliver a SEGV if they
  493                          * attempt to grow the thread stack past their
  494                          * current stacksize rlimit.  To avoid this,
  495                          * adjust vm_maxsaddr upwards to reflect
  496                          * the current stacksize rlimit rather
  497                          * than the maximum possible stacksize.
  498                          * It would be better to adjust the
  499                          * mmap'ed region, but some apps do not check
  500                          * mmap's return value.
  501                          */
  502                         mtx_assert(&Giant, MA_OWNED);
  503                         p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
  504                             p->p_rlimit[RLIMIT_STACK].rlim_cur;
  505                 }
  506 
  507                 /* This gives us our maximum stack size */
  508                 if (linux_args->len > STACK_SIZE - GUARD_SIZE)
  509                         bsd_args.len = linux_args->len;
  510                 else
  511                         bsd_args.len  = STACK_SIZE - GUARD_SIZE;
  512 
  513                 /* This gives us a new BOS.  If we're using VM_STACK, then
  514                  * mmap will just map the top SGROWSIZ bytes, and let
  515                  * the stack grow down to the limit at BOS.  If we're
  516                  * not using VM_STACK we map the full stack, since we
  517                  * don't have a way to autogrow it.
  518                  */
  519                 bsd_args.addr -= bsd_args.len;
  520         } else {
  521                 bsd_args.addr = linux_args->addr;
  522                 bsd_args.len  = linux_args->len;
  523         }
  524 
  525         bsd_args.prot = linux_args->prot | PROT_READ;   /* always required */
  526         if (linux_args->flags & LINUX_MAP_ANON)
  527                 bsd_args.fd = -1;
  528         else
  529                 bsd_args.fd = linux_args->fd;
  530         bsd_args.pos = linux_args->pos;
  531         bsd_args.pad = 0;
  532 
  533 #ifdef DEBUG
  534         if (ldebug(mmap))
  535                 printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n",
  536                     __func__,
  537                     (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
  538                     bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
  539 #endif
  540         error = mmap(td, &bsd_args);
  541 #ifdef DEBUG
  542         if (ldebug(mmap))
  543                 printf("-> %s() return: 0x%x (0x%08x)\n",
  544                         __func__, error, (u_int)td->td_retval[0]);
  545 #endif
  546         return (error);
  547 }
  548 
  549 int
  550 linux_pipe(struct thread *td, struct linux_pipe_args *args)
  551 {
  552         int error;
  553         int reg_edx;
  554 
  555 #ifdef DEBUG
  556         if (ldebug(pipe))
  557                 printf(ARGS(pipe, "*"));
  558 #endif
  559 
  560         reg_edx = td->td_retval[1];
  561         error = pipe(td, 0);
  562         if (error) {
  563                 td->td_retval[1] = reg_edx;
  564                 return (error);
  565         }
  566 
  567         error = copyout(td->td_retval, args->pipefds, 2*sizeof(int));
  568         if (error) {
  569                 td->td_retval[1] = reg_edx;
  570                 return (error);
  571         }
  572 
  573         td->td_retval[1] = reg_edx;
  574         td->td_retval[0] = 0;
  575         return (0);
  576 }
  577 
  578 int
  579 linux_ioperm(struct thread *td, struct linux_ioperm_args *args)
  580 {
  581         struct sysarch_args sa;
  582         struct i386_ioperm_args *iia;
  583         caddr_t sg;
  584 
  585         sg = stackgap_init();
  586         iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args));
  587         iia->start = args->start;
  588         iia->length = args->length;
  589         iia->enable = args->enable;
  590         sa.op = I386_SET_IOPERM;
  591         sa.parms = (char *)iia;
  592         return (sysarch(td, &sa));
  593 }
  594 
  595 int
  596 linux_iopl(struct thread *td, struct linux_iopl_args *args)
  597 {
  598         int error;
  599 
  600         if (args->level < 0 || args->level > 3)
  601                 return (EINVAL);
  602         if ((error = suser(td)) != 0)
  603                 return (error);
  604         if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
  605                 return (error);
  606         td->td_frame->tf_eflags = (td->td_frame->tf_eflags & ~PSL_IOPL) |
  607             (args->level * (PSL_IOPL / 3));
  608         return (0);
  609 }
  610 
  611 int
  612 linux_modify_ldt(struct thread *td, struct linux_modify_ldt_args *uap)
  613 {
  614         int error;
  615         caddr_t sg;
  616         struct sysarch_args args;
  617         struct i386_ldt_args *ldt;
  618         struct l_descriptor ld;
  619         union descriptor *desc;
  620 
  621         sg = stackgap_init();
  622 
  623         if (uap->ptr == NULL)
  624                 return (EINVAL);
  625 
  626         switch (uap->func) {
  627         case 0x00: /* read_ldt */
  628                 ldt = stackgap_alloc(&sg, sizeof(*ldt));
  629                 ldt->start = 0;
  630                 ldt->descs = uap->ptr;
  631                 ldt->num = uap->bytecount / sizeof(union descriptor);
  632                 args.op = I386_GET_LDT;
  633                 args.parms = (char*)ldt;
  634                 error = sysarch(td, &args);
  635                 td->td_retval[0] *= sizeof(union descriptor);
  636                 break;
  637         case 0x01: /* write_ldt */
  638         case 0x11: /* write_ldt */
  639                 if (uap->bytecount != sizeof(ld))
  640                         return (EINVAL);
  641 
  642                 error = copyin(uap->ptr, &ld, sizeof(ld));
  643                 if (error)
  644                         return (error);
  645 
  646                 ldt = stackgap_alloc(&sg, sizeof(*ldt));
  647                 desc = stackgap_alloc(&sg, sizeof(*desc));
  648                 ldt->start = ld.entry_number;
  649                 ldt->descs = desc;
  650                 ldt->num = 1;
  651                 desc->sd.sd_lolimit = (ld.limit & 0x0000ffff);
  652                 desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16;
  653                 desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff);
  654                 desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24;
  655                 desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) |
  656                         (ld.contents << 2);
  657                 desc->sd.sd_dpl = 3;
  658                 desc->sd.sd_p = (ld.seg_not_present ^ 1);
  659                 desc->sd.sd_xx = 0;
  660                 desc->sd.sd_def32 = ld.seg_32bit;
  661                 desc->sd.sd_gran = ld.limit_in_pages;
  662                 args.op = I386_SET_LDT;
  663                 args.parms = (char*)ldt;
  664                 error = sysarch(td, &args);
  665                 break;
  666         default:
  667                 error = EINVAL;
  668                 break;
  669         }
  670 
  671         if (error == EOPNOTSUPP) {
  672                 printf("linux: modify_ldt needs kernel option USER_LDT\n");
  673                 error = ENOSYS;
  674         }
  675 
  676         return (error);
  677 }
  678 
  679 int
  680 linux_sigaction(struct thread *td, struct linux_sigaction_args *args)
  681 {
  682         l_osigaction_t osa;
  683         l_sigaction_t act, oact;
  684         int error;
  685 
  686 #ifdef DEBUG
  687         if (ldebug(sigaction))
  688                 printf(ARGS(sigaction, "%d, %p, %p"),
  689                     args->sig, (void *)args->nsa, (void *)args->osa);
  690 #endif
  691 
  692         if (args->nsa != NULL) {
  693                 error = copyin(args->nsa, &osa, sizeof(l_osigaction_t));
  694                 if (error)
  695                         return (error);
  696                 act.lsa_handler = osa.lsa_handler;
  697                 act.lsa_flags = osa.lsa_flags;
  698                 act.lsa_restorer = osa.lsa_restorer;
  699                 LINUX_SIGEMPTYSET(act.lsa_mask);
  700                 act.lsa_mask.__bits[0] = osa.lsa_mask;
  701         }
  702 
  703         error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL,
  704             args->osa ? &oact : NULL);
  705 
  706         if (args->osa != NULL && !error) {
  707                 osa.lsa_handler = oact.lsa_handler;
  708                 osa.lsa_flags = oact.lsa_flags;
  709                 osa.lsa_restorer = oact.lsa_restorer;
  710                 osa.lsa_mask = oact.lsa_mask.__bits[0];
  711                 error = copyout(&osa, args->osa, sizeof(l_osigaction_t));
  712         }
  713 
  714         return (error);
  715 }
  716 
  717 /*
  718  * Linux has two extra args, restart and oldmask.  We dont use these,
  719  * but it seems that "restart" is actually a context pointer that
  720  * enables the signal to happen with a different register set.
  721  */
  722 int
  723 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args)
  724 {
  725         sigset_t sigmask;
  726         l_sigset_t mask;
  727 
  728 #ifdef DEBUG
  729         if (ldebug(sigsuspend))
  730                 printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask);
  731 #endif
  732 
  733         LINUX_SIGEMPTYSET(mask);
  734         mask.__bits[0] = args->mask;
  735         linux_to_bsd_sigset(&mask, &sigmask);
  736         return (kern_sigsuspend(td, sigmask));
  737 }
  738 
  739 int
  740 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
  741 {
  742         l_sigset_t lmask;
  743         sigset_t sigmask;
  744         int error;
  745 
  746 #ifdef DEBUG
  747         if (ldebug(rt_sigsuspend))
  748                 printf(ARGS(rt_sigsuspend, "%p, %d"),
  749                     (void *)uap->newset, uap->sigsetsize);
  750 #endif
  751 
  752         if (uap->sigsetsize != sizeof(l_sigset_t))
  753                 return (EINVAL);
  754 
  755         error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
  756         if (error)
  757                 return (error);
  758 
  759         linux_to_bsd_sigset(&lmask, &sigmask);
  760         return (kern_sigsuspend(td, sigmask));
  761 }
  762 
  763 int
  764 linux_pause(struct thread *td, struct linux_pause_args *args)
  765 {
  766         struct proc *p = td->td_proc;
  767         sigset_t sigmask;
  768 
  769 #ifdef DEBUG
  770         if (ldebug(pause))
  771                 printf(ARGS(pause, ""));
  772 #endif
  773 
  774         PROC_LOCK(p);
  775         sigmask = td->td_sigmask;
  776         PROC_UNLOCK(p);
  777         return (kern_sigsuspend(td, sigmask));
  778 }
  779 
  780 int
  781 linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
  782 {
  783         stack_t ss, oss;
  784         l_stack_t lss;
  785         int error;
  786 
  787 #ifdef DEBUG
  788         if (ldebug(sigaltstack))
  789                 printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss);
  790 #endif
  791 
  792         if (uap->uss != NULL) {
  793                 error = copyin(uap->uss, &lss, sizeof(l_stack_t));
  794                 if (error)
  795                         return (error);
  796 
  797                 ss.ss_sp = lss.ss_sp;
  798                 ss.ss_size = lss.ss_size;
  799                 ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
  800         }
  801         error = kern_sigaltstack(td, (uap->uoss != NULL) ? &oss : NULL,
  802             (uap->uss != NULL) ? &ss : NULL);
  803         if (!error && uap->uoss != NULL) {
  804                 lss.ss_sp = oss.ss_sp;
  805                 lss.ss_size = oss.ss_size;
  806                 lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
  807                 error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
  808         }
  809 
  810         return (error);
  811 }
  812 
  813 int
  814 linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args)
  815 {
  816         struct ftruncate_args sa;
  817 
  818 #ifdef DEBUG
  819         if (ldebug(ftruncate64))
  820                 printf(ARGS(ftruncate64, "%u, %jd"), args->fd,
  821                     (intmax_t)args->length);
  822 #endif
  823 
  824         sa.fd = args->fd;
  825         sa.pad = 0;
  826         sa.length = args->length;
  827         return ftruncate(td, &sa);
  828 }

Cache object: f11b48ba493cafe705c2af82fbb2b96d


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