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

Cache object: 212639e674e3ab664db2d442d572f85e


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