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/ia64/ia32/ia32_trap.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) 2004 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  *
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   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  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/ktr.h>
   33 #include <sys/sysproto.h>
   34 #include <sys/kernel.h>
   35 #include <sys/lock.h>
   36 #include <sys/mutex.h>
   37 #include <sys/pioctl.h>
   38 #include <sys/proc.h>
   39 #include <sys/ptrace.h>
   40 #include <sys/signalvar.h>
   41 #include <sys/syscall.h>
   42 #include <sys/sysent.h>
   43 #include <machine/cpu.h>
   44 #include <machine/fpu.h>
   45 #include <machine/frame.h>
   46 #include <machine/md_var.h>
   47 #include <i386/include/psl.h>
   48 
   49 #include <security/audit/audit.h>
   50 
   51 #include <compat/ia32/ia32_util.h>
   52 
   53 void
   54 ia32_set_syscall_retval(struct thread *td, int error)
   55 {
   56         struct proc *p;
   57         struct trapframe *tf;
   58 
   59         tf = td->td_frame;
   60 
   61         switch (error) {
   62         case 0:
   63                 tf->tf_scratch.gr8 = td->td_retval[0];  /* eax */
   64                 tf->tf_scratch.gr10 = td->td_retval[1]; /* edx */
   65                 ia64_set_eflag(ia64_get_eflag() & ~PSL_C);
   66                 break;
   67 
   68         case ERESTART:
   69                 /*
   70                  * Reconstruct pc, assuming lcall $X,y is 7 bytes,
   71                  * int 0x80 is 2 bytes. XXX Assume int 0x80.
   72                  */
   73                 tf->tf_special.iip -= 2;
   74                 break;
   75 
   76         case EJUSTRETURN:
   77                 break;
   78 
   79         default:
   80                 p = td->td_proc;
   81                 if (p->p_sysent->sv_errsize) {
   82                         if (error >= p->p_sysent->sv_errsize)
   83                                 error = -1;     /* XXX */
   84                         else
   85                                 error = p->p_sysent->sv_errtbl[error];
   86                 }
   87                 tf->tf_scratch.gr8 = error;
   88                 ia64_set_eflag(ia64_get_eflag() | PSL_C);
   89                 break;
   90         }
   91 }
   92 
   93 int
   94 ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
   95 {
   96         struct trapframe *tf;
   97         struct proc *p;
   98         uint32_t args[8];
   99         caddr_t params;
  100         int error, i;
  101 
  102         tf = td->td_frame;
  103         p = td->td_proc;
  104 
  105         params = (caddr_t)(tf->tf_special.sp & ((1L<<32)-1)) +
  106             sizeof(uint32_t);
  107         sa->code = tf->tf_scratch.gr8;          /* eax */
  108 
  109         if (sa->code == SYS_syscall) {
  110                 /* Code is first argument, followed by actual args. */
  111                 sa->code = fuword32(params);
  112                 params += sizeof(int);
  113         } else if (sa->code == SYS___syscall) {
  114                 /*
  115                  * Like syscall, but code is a quad, so as to maintain
  116                  * quad alignment for the rest of the arguments.  We
  117                  * use a 32-bit fetch in case params is not aligned.
  118                  */
  119                 sa->code = fuword32(params);
  120                 params += sizeof(quad_t);
  121         }
  122 
  123         if (p->p_sysent->sv_mask)
  124                 sa->code &= p->p_sysent->sv_mask;
  125         if (sa->code >= p->p_sysent->sv_size)
  126                 sa->callp = &p->p_sysent->sv_table[0];
  127         else
  128                 sa->callp = &p->p_sysent->sv_table[sa->code];
  129         sa->narg = sa->callp->sy_narg;
  130 
  131         if (params != NULL && sa->narg != 0)
  132                 error = copyin(params, (caddr_t)args, sa->narg * sizeof(int));
  133         else
  134                 error = 0;
  135         sa->args = &sa->args32[0];
  136 
  137         if (error == 0) {
  138                 for (i = 0; i < sa->narg; i++)
  139                         sa->args32[i] = args[i];
  140                 td->td_retval[0] = 0;
  141                 td->td_retval[1] = tf->tf_scratch.gr10; /* edx */
  142         }
  143 
  144         return (error);
  145 }
  146 
  147 #include "../../kern/subr_syscall.c"
  148 
  149 static void
  150 ia32_syscall(struct trapframe *tf)
  151 {
  152         struct thread *td;
  153         struct syscall_args sa;
  154         register_t eflags;
  155         int error;
  156         ksiginfo_t ksi;
  157 
  158         td = curthread;
  159         eflags = ia64_get_eflag();
  160 
  161         error = syscallenter(td, &sa);
  162 
  163         /*
  164          * Traced syscall.
  165          */
  166         if ((eflags & PSL_T) && !(eflags & PSL_VM)) {
  167                 ia64_set_eflag(ia64_get_eflag() & ~PSL_T);
  168                 ksiginfo_init_trap(&ksi);
  169                 ksi.ksi_signo = SIGTRAP;
  170                 ksi.ksi_code = TRAP_TRACE;
  171                 ksi.ksi_addr = (void *)tf->tf_special.iip;
  172                 trapsignal(td, &ksi);
  173         }
  174 
  175         syscallret(td, error, &sa);
  176 }
  177 
  178 /*
  179  * ia32_trap() is called from exception.S to handle the IA-32 specific
  180  * interruption vectors.
  181  */
  182 void
  183 ia32_trap(int vector, struct trapframe *tf)
  184 {
  185         struct proc *p;
  186         struct thread *td;
  187         uint64_t ucode;
  188         int sig;
  189         ksiginfo_t ksi;
  190 
  191         KASSERT(TRAPF_USERMODE(tf), ("%s: In kernel mode???", __func__));
  192 
  193         ia64_set_fpsr(IA64_FPSR_DEFAULT);
  194         PCPU_INC(cnt.v_trap);
  195 
  196         td = curthread;
  197         td->td_frame = tf;
  198         td->td_pticks = 0;
  199         p = td->td_proc;
  200         if (td->td_ucred != p->p_ucred)
  201                 cred_update_thread(td);
  202         sig = 0;
  203         ucode = 0;
  204         switch (vector) {
  205         case IA64_VEC_IA32_EXCEPTION:
  206                 switch ((tf->tf_special.isr >> 16) & 0xffff) {
  207                 case IA32_EXCEPTION_DIVIDE:
  208                         ucode = FPE_INTDIV;
  209                         sig = SIGFPE;
  210                         break;
  211                 case IA32_EXCEPTION_DEBUG:
  212                 case IA32_EXCEPTION_BREAK:
  213                         sig = SIGTRAP;
  214                         break;
  215                 case IA32_EXCEPTION_OVERFLOW:
  216                         ucode = FPE_INTOVF;
  217                         sig = SIGFPE;
  218                         break;
  219                 case IA32_EXCEPTION_BOUND:
  220                         ucode = FPE_FLTSUB;
  221                         sig = SIGFPE;
  222                         break;
  223                 case IA32_EXCEPTION_DNA:
  224                         ucode = 0;
  225                         sig = SIGFPE;
  226                         break;
  227                 case IA32_EXCEPTION_NOT_PRESENT:
  228                 case IA32_EXCEPTION_STACK_FAULT:
  229                 case IA32_EXCEPTION_GPFAULT:
  230                         ucode = (tf->tf_special.isr & 0xffff) + BUS_SEGM_FAULT;
  231                         sig = SIGBUS;
  232                         break;
  233                 case IA32_EXCEPTION_FPERROR:
  234                         ucode = 0;      /* XXX */
  235                         sig = SIGFPE;
  236                         break;
  237                 case IA32_EXCEPTION_ALIGNMENT_CHECK:
  238                         ucode = tf->tf_special.ifa;     /* VA */
  239                         sig = SIGBUS;
  240                         break;
  241                 case IA32_EXCEPTION_STREAMING_SIMD:
  242                         ucode = 0; /* XXX */
  243                         sig = SIGFPE;
  244                         break;
  245                 default:
  246                         trap_panic(vector, tf);
  247                         break;
  248                 }
  249                 break;
  250 
  251         case IA64_VEC_IA32_INTERCEPT:
  252                 /* XXX Maybe need to emulate ia32 instruction. */
  253                 trap_panic(vector, tf);
  254 
  255         case IA64_VEC_IA32_INTERRUPT:
  256                 /* INT n instruction - probably a syscall. */
  257                 if (((tf->tf_special.isr >> 16) & 0xffff) == 0x80) {
  258                         ia32_syscall(tf);
  259                         goto out;
  260                 }
  261                 ucode = (tf->tf_special.isr >> 16) & 0xffff;
  262                 sig = SIGILL;
  263                 break;
  264 
  265         default:
  266                 /* Should never happen of course. */
  267                 trap_panic(vector, tf);
  268                 break;
  269         }
  270 
  271         KASSERT(sig != 0, ("%s: signal not set", __func__));
  272 
  273         ksiginfo_init_trap(&ksi);
  274         ksi.ksi_signo = sig;
  275         ksi.ksi_code = (int)ucode; /* XXX */
  276         /* ksi.ksi_addr */
  277         trapsignal(td, &ksi);
  278 
  279 out:
  280         userret(td, tf);
  281         mtx_assert(&Giant, MA_NOTOWNED);
  282         do_ast(tf);
  283 }

Cache object: aae49c77047f4ba36fbc460492ea1ac3


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