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/amd64/ia32/ia32_syscall.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, David Greenman
    3  * Copyright (c) 1990, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * the University of Utah, and William Jolitz.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by the University of
   20  *      California, Berkeley and its contributors.
   21  * 4. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD: releng/5.4/sys/amd64/ia32/ia32_syscall.c 134679 2004-09-03 06:11:59Z julian $");
   40 
   41 /*
   42  * 386 Trap and System call handling
   43  */
   44 
   45 #include "opt_clock.h"
   46 #include "opt_cpu.h"
   47 #include "opt_isa.h"
   48 #include "opt_ktrace.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/bus.h>
   52 #include <sys/systm.h>
   53 #include <sys/proc.h>
   54 #include <sys/pioctl.h>
   55 #include <sys/kernel.h>
   56 #include <sys/ktr.h>
   57 #include <sys/lock.h>
   58 #include <sys/mutex.h>
   59 #include <sys/resourcevar.h>
   60 #include <sys/signalvar.h>
   61 #include <sys/syscall.h>
   62 #include <sys/sysctl.h>
   63 #include <sys/sysent.h>
   64 #include <sys/uio.h>
   65 #include <sys/vmmeter.h>
   66 #ifdef KTRACE
   67 #include <sys/ktrace.h>
   68 #endif
   69 
   70 #include <vm/vm.h>
   71 #include <vm/vm_param.h>
   72 #include <vm/pmap.h>
   73 #include <vm/vm_kern.h>
   74 #include <vm/vm_map.h>
   75 #include <vm/vm_page.h>
   76 #include <vm/vm_extern.h>
   77 
   78 #include <machine/cpu.h>
   79 #include <machine/intr_machdep.h>
   80 #include <machine/md_var.h>
   81 
   82 #define IDTVEC(name)    __CONCAT(X,name)
   83 
   84 extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(rsvd);
   85 extern const char *freebsd32_syscallnames[];
   86 
   87 void ia32_syscall(struct trapframe frame);      /* Called from asm code */
   88 
   89 void
   90 ia32_syscall(struct trapframe frame)
   91 {
   92         caddr_t params;
   93         int i;
   94         struct sysent *callp;
   95         struct thread *td = curthread;
   96         struct proc *p = td->td_proc;
   97         register_t orig_tf_rflags;
   98         u_int sticks;
   99         int error;
  100         int narg;
  101         u_int32_t args[8];
  102         u_int64_t args64[8];
  103         u_int code;
  104 
  105         /*
  106          * note: PCPU_LAZY_INC() can only be used if we can afford
  107          * occassional inaccuracy in the count.
  108          */
  109         cnt.v_syscall++;
  110 
  111         sticks = td->td_sticks;
  112         td->td_frame = &frame;
  113         if (td->td_ucred != p->p_ucred) 
  114                 cred_update_thread(td);
  115         params = (caddr_t)frame.tf_rsp + sizeof(u_int32_t);
  116         code = frame.tf_rax;
  117         orig_tf_rflags = frame.tf_rflags;
  118 
  119         if (p->p_sysent->sv_prepsyscall) {
  120                 /*
  121                  * The prep code is MP aware.
  122                  */
  123                 (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, &params);
  124         } else {
  125                 /*
  126                  * Need to check if this is a 32 bit or 64 bit syscall.
  127                  * fuword is MP aware.
  128                  */
  129                 if (code == SYS_syscall) {
  130                         /*
  131                          * Code is first argument, followed by actual args.
  132                          */
  133                         code = fuword32(params);
  134                         params += sizeof(int);
  135                 } else if (code == SYS___syscall) {
  136                         /*
  137                          * Like syscall, but code is a quad, so as to maintain
  138                          * quad alignment for the rest of the arguments.
  139                          * We use a 32-bit fetch in case params is not
  140                          * aligned.
  141                          */
  142                         code = fuword32(params);
  143                         params += sizeof(quad_t);
  144                 }
  145         }
  146 
  147         if (p->p_sysent->sv_mask)
  148                 code &= p->p_sysent->sv_mask;
  149 
  150         if (code >= p->p_sysent->sv_size)
  151                 callp = &p->p_sysent->sv_table[0];
  152         else
  153                 callp = &p->p_sysent->sv_table[code];
  154 
  155         narg = callp->sy_narg & SYF_ARGMASK;
  156 
  157         /*
  158          * copyin and the ktrsyscall()/ktrsysret() code is MP-aware
  159          */
  160         if (params != NULL && narg != 0)
  161                 error = copyin(params, (caddr_t)args,
  162                     (u_int)(narg * sizeof(int)));
  163         else
  164                 error = 0;
  165 
  166         for (i = 0; i < narg; i++)
  167                 args64[i] = args[i];
  168 
  169 #ifdef KTRACE
  170         if (KTRPOINT(td, KTR_SYSCALL))
  171                 ktrsyscall(code, narg, args64);
  172 #endif
  173         /*
  174          * Try to run the syscall without Giant if the syscall
  175          * is MP safe.
  176          */
  177         if ((callp->sy_narg & SYF_MPSAFE) == 0)
  178                 mtx_lock(&Giant);
  179 
  180         if (error == 0) {
  181                 td->td_retval[0] = 0;
  182                 td->td_retval[1] = frame.tf_rdx;
  183 
  184                 STOPEVENT(p, S_SCE, narg);
  185 
  186                 error = (*callp->sy_call)(td, args64);
  187         }
  188 
  189         switch (error) {
  190         case 0:
  191                 frame.tf_rax = td->td_retval[0];
  192                 frame.tf_rdx = td->td_retval[1];
  193                 frame.tf_rflags &= ~PSL_C;
  194                 break;
  195 
  196         case ERESTART:
  197                 /*
  198                  * Reconstruct pc, assuming lcall $X,y is 7 bytes,
  199                  * int 0x80 is 2 bytes. We saved this in tf_err.
  200                  */
  201                 frame.tf_rip -= frame.tf_err;
  202                 break;
  203 
  204         case EJUSTRETURN:
  205                 break;
  206 
  207         default:
  208                 if (p->p_sysent->sv_errsize) {
  209                         if (error >= p->p_sysent->sv_errsize)
  210                                 error = -1;     /* XXX */
  211                         else
  212                                 error = p->p_sysent->sv_errtbl[error];
  213                 }
  214                 frame.tf_rax = error;
  215                 frame.tf_rflags |= PSL_C;
  216                 break;
  217         }
  218 
  219         /*
  220          * Release Giant if we previously set it.
  221          */
  222         if ((callp->sy_narg & SYF_MPSAFE) == 0)
  223                 mtx_unlock(&Giant);
  224 
  225         /*
  226          * Traced syscall.
  227          */
  228         if (orig_tf_rflags & PSL_T) {
  229                 frame.tf_rflags &= ~PSL_T;
  230                 trapsignal(td, SIGTRAP, 0);
  231         }
  232 
  233         /*
  234          * Handle reschedule and other end-of-syscall issues
  235          */
  236         userret(td, &frame, sticks);
  237 
  238 #ifdef KTRACE
  239         if (KTRPOINT(td, KTR_SYSRET))
  240                 ktrsysret(code, error, td->td_retval[0]);
  241 #endif
  242 
  243         /*
  244          * This works because errno is findable through the
  245          * register set.  If we ever support an emulation where this
  246          * is not the case, this code will need to be revisited.
  247          */
  248         STOPEVENT(p, S_SCX, code);
  249 
  250         WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
  251             (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???");
  252         mtx_assert(&sched_lock, MA_NOTOWNED);
  253         mtx_assert(&Giant, MA_NOTOWNED);
  254 }
  255 
  256 
  257 static void
  258 ia32_syscall_enable(void *dummy)
  259 {
  260 
  261         setidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall), SDT_SYSIGT, SEL_UPL, 0);
  262 }
  263 
  264 static void
  265 ia32_syscall_disable(void *dummy)
  266 {
  267 
  268         setidt(IDT_SYSCALL, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
  269 }
  270 
  271 SYSINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_enable, NULL);
  272 SYSUNINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_disable, NULL);

Cache object: 944e9e33ebc99bbcd40a784a931cae57


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