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/sparc64/sparc64/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) 2001, Jake Burkholder
    3  * Copyright (C) 1994, David Greenman
    4  * Copyright (c) 1990, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * the University of Utah, and William Jolitz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      from: @(#)trap.c        7.4 (Berkeley) 5/13/91
   35  *      from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40 
   41 #include "opt_ddb.h"
   42 #include "opt_ktr.h"
   43 #include "opt_ktrace.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/kdb.h>
   47 #include <sys/kernel.h>
   48 #include <sys/bus.h>
   49 #include <sys/interrupt.h>
   50 #include <sys/ktr.h>
   51 #include <sys/lock.h>
   52 #include <sys/mutex.h>
   53 #include <sys/systm.h>
   54 #include <sys/pcpu.h>
   55 #include <sys/pioctl.h>
   56 #include <sys/ptrace.h>
   57 #include <sys/proc.h>
   58 #include <sys/smp.h>
   59 #include <sys/signalvar.h>
   60 #include <sys/syscall.h>
   61 #include <sys/sysctl.h>
   62 #include <sys/sysent.h>
   63 #include <sys/vmmeter.h>
   64 #ifdef KTRACE
   65 #include <sys/uio.h>
   66 #include <sys/ktrace.h>
   67 #endif
   68 #include <security/audit/audit.h>
   69 
   70 #include <dev/ofw/openfirm.h>
   71 
   72 #include <vm/vm.h>
   73 #include <vm/pmap.h>
   74 #include <vm/vm_extern.h>
   75 #include <vm/vm_param.h>
   76 #include <vm/vm_kern.h>
   77 #include <vm/vm_map.h>
   78 #include <vm/vm_page.h>
   79 
   80 #include <machine/cpu.h>
   81 #include <machine/frame.h>
   82 #include <machine/intr_machdep.h>
   83 #include <machine/ofw_machdep.h>
   84 #include <machine/pcb.h>
   85 #include <machine/smp.h>
   86 #include <machine/trap.h>
   87 #include <machine/tstate.h>
   88 #include <machine/tte.h>
   89 #include <machine/tlb.h>
   90 #include <machine/tsb.h>
   91 #include <machine/watch.h>
   92 
   93 void trap(struct trapframe *tf);
   94 void syscall(struct trapframe *tf);
   95 
   96 static int trap_cecc(void);
   97 static int trap_pfault(struct thread *td, struct trapframe *tf);
   98 
   99 extern char copy_fault[];
  100 extern char copy_nofault_begin[];
  101 extern char copy_nofault_end[];
  102 
  103 extern char fs_fault[];
  104 extern char fs_nofault_begin[];
  105 extern char fs_nofault_end[];
  106 extern char fs_nofault_intr_begin[];
  107 extern char fs_nofault_intr_end[];
  108 
  109 extern char fas_fault[];
  110 extern char fas_nofault_begin[];
  111 extern char fas_nofault_end[];
  112 
  113 const char *const trap_msg[] = {
  114         "reserved",
  115         "instruction access exception",
  116         "instruction access error",
  117         "instruction access protection",
  118         "illtrap instruction",
  119         "illegal instruction",
  120         "privileged opcode",
  121         "floating point disabled",
  122         "floating point exception ieee 754",
  123         "floating point exception other",
  124         "tag overflow",
  125         "division by zero",
  126         "data access exception",
  127         "data access error",
  128         "data access protection",
  129         "memory address not aligned",
  130         "privileged action",
  131         "async data error",
  132         "trap instruction 16",
  133         "trap instruction 17",
  134         "trap instruction 18",
  135         "trap instruction 19",
  136         "trap instruction 20",
  137         "trap instruction 21",
  138         "trap instruction 22",
  139         "trap instruction 23",
  140         "trap instruction 24",
  141         "trap instruction 25",
  142         "trap instruction 26",
  143         "trap instruction 27",
  144         "trap instruction 28",
  145         "trap instruction 29",
  146         "trap instruction 30",
  147         "trap instruction 31",
  148         "fast instruction access mmu miss",
  149         "fast data access mmu miss",
  150         "interrupt",
  151         "physical address watchpoint",
  152         "virtual address watchpoint",
  153         "corrected ecc error",
  154         "spill",
  155         "fill",
  156         "fill",
  157         "breakpoint",
  158         "clean window",
  159         "range check",
  160         "fix alignment",
  161         "integer overflow",
  162         "syscall",
  163         "restore physical watchpoint",
  164         "restore virtual watchpoint",
  165         "kernel stack fault",
  166 };
  167 
  168 static const int trap_sig[] = {
  169         SIGILL,                 /* reserved */
  170         SIGILL,                 /* instruction access exception */
  171         SIGILL,                 /* instruction access error */
  172         SIGILL,                 /* instruction access protection */
  173         SIGILL,                 /* illtrap instruction */
  174         SIGILL,                 /* illegal instruction */
  175         SIGBUS,                 /* privileged opcode */
  176         SIGFPE,                 /* floating point disabled */
  177         SIGFPE,                 /* floating point exception ieee 754 */
  178         SIGFPE,                 /* floating point exception other */
  179         SIGEMT,                 /* tag overflow */
  180         SIGFPE,                 /* division by zero */
  181         SIGILL,                 /* data access exception */
  182         SIGILL,                 /* data access error */
  183         SIGBUS,                 /* data access protection */
  184         SIGBUS,                 /* memory address not aligned */
  185         SIGBUS,                 /* privileged action */
  186         SIGBUS,                 /* async data error */
  187         SIGILL,                 /* trap instruction 16 */
  188         SIGILL,                 /* trap instruction 17 */
  189         SIGILL,                 /* trap instruction 18 */
  190         SIGILL,                 /* trap instruction 19 */
  191         SIGILL,                 /* trap instruction 20 */
  192         SIGILL,                 /* trap instruction 21 */
  193         SIGILL,                 /* trap instruction 22 */
  194         SIGILL,                 /* trap instruction 23 */
  195         SIGILL,                 /* trap instruction 24 */
  196         SIGILL,                 /* trap instruction 25 */
  197         SIGILL,                 /* trap instruction 26 */
  198         SIGILL,                 /* trap instruction 27 */
  199         SIGILL,                 /* trap instruction 28 */
  200         SIGILL,                 /* trap instruction 29 */
  201         SIGILL,                 /* trap instruction 30 */
  202         SIGILL,                 /* trap instruction 31 */
  203         SIGSEGV,                /* fast instruction access mmu miss */
  204         SIGSEGV,                /* fast data access mmu miss */
  205         -1,                     /* interrupt */
  206         -1,                     /* physical address watchpoint */
  207         -1,                     /* virtual address watchpoint */
  208         -1,                     /* corrected ecc error */
  209         SIGILL,                 /* spill */
  210         SIGILL,                 /* fill */
  211         SIGILL,                 /* fill */
  212         SIGTRAP,                /* breakpoint */
  213         SIGILL,                 /* clean window */
  214         SIGILL,                 /* range check */
  215         SIGILL,                 /* fix alignment */
  216         SIGILL,                 /* integer overflow */
  217         SIGSYS,                 /* syscall */
  218         -1,                     /* restore physical watchpoint */
  219         -1,                     /* restore virtual watchpoint */
  220         -1,                     /* kernel stack fault */
  221 };
  222 
  223 CTASSERT(sizeof(trap_msg) / sizeof(*trap_msg) == T_MAX);
  224 CTASSERT(sizeof(trap_sig) / sizeof(*trap_sig) == T_MAX);
  225 
  226 CTASSERT(sizeof(struct trapframe) == 256);
  227 
  228 int debugger_on_signal = 0;
  229 SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
  230     &debugger_on_signal, 0, "");
  231 
  232 u_int corrected_ecc = 0;
  233 SYSCTL_UINT(_machdep, OID_AUTO, corrected_ecc, CTLFLAG_RD, &corrected_ecc, 0,
  234     "corrected ECC errors");
  235 
  236 /*
  237  * SUNW,set-trap-table allows to take over %tba from the PROM, which
  238  * will turn off interrupts and handle outstanding ones while doing so,
  239  * in a safe way.
  240  */
  241 void
  242 sun4u_set_traptable(void *tba_addr)
  243 {
  244         static struct {
  245                 cell_t name;
  246                 cell_t nargs;
  247                 cell_t nreturns;
  248                 cell_t tba_addr;
  249         } args = {
  250                 (cell_t)"SUNW,set-trap-table",
  251                 1,
  252                 0,
  253         };
  254 
  255         args.tba_addr = (cell_t)tba_addr;
  256         ofw_entry(&args);
  257 }
  258 
  259 void
  260 trap(struct trapframe *tf)
  261 {
  262         struct thread *td;
  263         struct proc *p;
  264         int error;
  265         int sig;
  266         register_t addr;
  267         ksiginfo_t ksi;
  268 
  269         td = curthread;
  270 
  271         CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
  272             trap_msg[tf->tf_type & ~T_KERNEL],
  273             (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
  274 
  275         PCPU_INC(cnt.v_trap);
  276 
  277         if ((tf->tf_tstate & TSTATE_PRIV) == 0) {
  278                 KASSERT(td != NULL, ("trap: curthread NULL"));
  279                 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
  280 
  281                 p = td->td_proc;
  282                 td->td_pticks = 0;
  283                 td->td_frame = tf;
  284                 addr = tf->tf_tpc;
  285                 if (td->td_ucred != p->p_ucred)
  286                         cred_update_thread(td);
  287 
  288                 switch (tf->tf_type) {
  289                 case T_DATA_MISS:
  290                 case T_DATA_PROTECTION:
  291                         addr = tf->tf_sfar;
  292                         /* FALLTHROUGH */
  293                 case T_INSTRUCTION_MISS:
  294                         sig = trap_pfault(td, tf);
  295                         break;
  296                 case T_FILL:
  297                         sig = rwindow_load(td, tf, 2);
  298                         break;
  299                 case T_FILL_RET:
  300                         sig = rwindow_load(td, tf, 1);
  301                         break;
  302                 case T_SPILL:
  303                         sig = rwindow_save(td);
  304                         break;
  305                 case T_CORRECTED_ECC_ERROR:
  306                         sig = trap_cecc();
  307                         break;
  308                 default:
  309                         if (tf->tf_type > T_MAX)
  310                                 panic("trap: bad trap type %#lx (user)",
  311                                     tf->tf_type);
  312                         else if (trap_sig[tf->tf_type] == -1)
  313                                 panic("trap: %s (user)",
  314                                     trap_msg[tf->tf_type]);
  315                         sig = trap_sig[tf->tf_type];
  316                         break;
  317                 }
  318 
  319                 if (sig != 0) {
  320                         /* Translate fault for emulators. */
  321                         if (p->p_sysent->sv_transtrap != NULL) {
  322                                 sig = p->p_sysent->sv_transtrap(sig,
  323                                     tf->tf_type);
  324                         }
  325                         if (debugger_on_signal &&
  326                             (sig == 4 || sig == 10 || sig == 11))
  327                                 kdb_enter(KDB_WHY_TRAPSIG, "trapsig");
  328                         ksiginfo_init_trap(&ksi);
  329                         ksi.ksi_signo = sig;
  330                         ksi.ksi_code = (int)tf->tf_type; /* XXX not POSIX */
  331                         ksi.ksi_addr = (void *)addr;
  332                         ksi.ksi_trapno = (int)tf->tf_type;
  333                         trapsignal(td, &ksi);
  334                 }
  335 
  336                 userret(td, tf);
  337                 mtx_assert(&Giant, MA_NOTOWNED);
  338         } else {
  339                 KASSERT((tf->tf_type & T_KERNEL) != 0,
  340                     ("trap: kernel trap isn't"));
  341 
  342                 if (kdb_active) {
  343                         kdb_reenter();
  344                         return;
  345                 }
  346 
  347                 switch (tf->tf_type & ~T_KERNEL) {
  348                 case T_BREAKPOINT:
  349                 case T_KSTACK_FAULT:
  350                         error = (kdb_trap(tf->tf_type, 0, tf) == 0);
  351                         TF_DONE(tf);
  352                         break;
  353 #ifdef notyet
  354                 case T_PA_WATCHPOINT:
  355                 case T_VA_WATCHPOINT:
  356                         error = db_watch_trap(tf);
  357                         break;
  358 #endif
  359                 case T_DATA_MISS:
  360                 case T_DATA_PROTECTION:
  361                 case T_INSTRUCTION_MISS:
  362                         error = trap_pfault(td, tf);
  363                         break;
  364                 case T_DATA_EXCEPTION:
  365                 case T_MEM_ADDRESS_NOT_ALIGNED:
  366                         if ((tf->tf_sfsr & MMU_SFSR_FV) != 0 &&
  367                             MMU_SFSR_GET_ASI(tf->tf_sfsr) == ASI_AIUP) {
  368                                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
  369                                     tf->tf_tpc <= (u_long)copy_nofault_end) {
  370                                         tf->tf_tpc = (u_long)copy_fault;
  371                                         tf->tf_tnpc = tf->tf_tpc + 4;
  372                                         error = 0;
  373                                         break;
  374                                 }
  375                                 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
  376                                     tf->tf_tpc <= (u_long)fs_nofault_end) {
  377                                         tf->tf_tpc = (u_long)fs_fault;
  378                                         tf->tf_tnpc = tf->tf_tpc + 4;
  379                                         error = 0;
  380                                         break;
  381                                 }
  382                         }
  383                         error = 1;
  384                         break;
  385                 case T_DATA_ERROR:
  386                         /*
  387                          * Handle PCI poke/peek as per UltraSPARC IIi
  388                          * User's Manual 16.2.1, modulo checking the
  389                          * TPC as USIII CPUs generate a precise trap
  390                          * instead of a special deferred one.
  391                          */
  392                         if (tf->tf_tpc > (u_long)fas_nofault_begin &&
  393                             tf->tf_tpc < (u_long)fas_nofault_end) {
  394                                 cache_flush();
  395                                 cache_enable(PCPU_GET(impl));
  396                                 tf->tf_tpc = (u_long)fas_fault;
  397                                 tf->tf_tnpc = tf->tf_tpc + 4;
  398                                 error = 0;
  399                                 break;
  400                         }
  401                         error = 1;
  402                         break;
  403                 case T_CORRECTED_ECC_ERROR:
  404                         error = trap_cecc();
  405                         break;
  406                 default:
  407                         error = 1;
  408                         break;
  409                 }
  410 
  411                 if (error != 0) {
  412                         tf->tf_type &= ~T_KERNEL;
  413                         if (tf->tf_type > T_MAX)
  414                                 panic("trap: bad trap type %#lx (kernel)",
  415                                     tf->tf_type);
  416                         panic("trap: %s (kernel)", trap_msg[tf->tf_type]);
  417                 }
  418         }
  419         CTR1(KTR_TRAP, "trap: td=%p return", td);
  420 }
  421 
  422 static int
  423 trap_cecc(void)
  424 {
  425         u_long eee;
  426 
  427         /*
  428          * Turn off (non-)correctable error reporting while we're dealing
  429          * with the error.
  430          */
  431         eee = ldxa(0, ASI_ESTATE_ERROR_EN_REG);
  432         stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee & ~(AA_ESTATE_NCEEN |
  433             AA_ESTATE_CEEN));
  434         /* Flush the caches in order ensure no corrupt data got installed. */
  435         cache_flush();
  436         /* Ensure the caches are still turned on (should be). */
  437         cache_enable(PCPU_GET(impl));
  438         /* Clear the error from the AFSR. */
  439         stxa_sync(0, ASI_AFSR, ldxa(0, ASI_AFSR));
  440         corrected_ecc++;
  441         printf("corrected ECC error\n");
  442         /* Turn (non-)correctable error reporting back on. */
  443         stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee);
  444         return (0);
  445 }
  446 
  447 static int
  448 trap_pfault(struct thread *td, struct trapframe *tf)
  449 {
  450         struct vmspace *vm;
  451         struct proc *p;
  452         vm_offset_t va;
  453         vm_prot_t prot;
  454         vm_map_entry_t entry;
  455         u_long ctx;
  456         int flags;
  457         int type;
  458         int rv;
  459 
  460         if (td == NULL)
  461                 return (-1);
  462         KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
  463         KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
  464         KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
  465 
  466         p = td->td_proc;
  467 
  468         rv = KERN_SUCCESS;
  469         ctx = TLB_TAR_CTX(tf->tf_tar);
  470         type = tf->tf_type & ~T_KERNEL;
  471         va = TLB_TAR_VA(tf->tf_tar);
  472 
  473         CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
  474             td, p->p_vmspace->vm_pmap.pm_context[curcpu], va, ctx);
  475 
  476         if (type == T_DATA_PROTECTION) {
  477                 prot = VM_PROT_WRITE;
  478                 flags = VM_FAULT_DIRTY;
  479         } else {
  480                 if (type == T_DATA_MISS)
  481                         prot = VM_PROT_READ;
  482                 else
  483                         prot = VM_PROT_READ | VM_PROT_EXECUTE;
  484                 flags = VM_FAULT_NORMAL;
  485         }
  486 
  487         if (ctx != TLB_CTX_KERNEL) {
  488                 if ((tf->tf_tstate & TSTATE_PRIV) != 0 &&
  489                     (tf->tf_tpc >= (u_long)fs_nofault_intr_begin &&
  490                     tf->tf_tpc <= (u_long)fs_nofault_intr_end)) {
  491                         tf->tf_tpc = (u_long)fs_fault;
  492                         tf->tf_tnpc = tf->tf_tpc + 4;
  493                         return (0);
  494                 }
  495 
  496                 /*
  497                  * This is a fault on non-kernel virtual memory.
  498                  */
  499                 vm = p->p_vmspace;
  500 
  501                 /*
  502                  * Keep swapout from messing with us during this
  503                  * critical time.
  504                  */
  505                 PROC_LOCK(p);
  506                 ++p->p_lock;
  507                 PROC_UNLOCK(p);
  508 
  509                 /* Fault in the user page. */
  510                 rv = vm_fault(&vm->vm_map, va, prot, flags);
  511 
  512                 /*
  513                  * Now the process can be swapped again.
  514                  */
  515                 PROC_LOCK(p);
  516                 --p->p_lock;
  517                 PROC_UNLOCK(p);
  518         } else {
  519                 /*
  520                  * This is a fault on kernel virtual memory.  Attempts to
  521                  * access kernel memory from user mode cause privileged
  522                  * action traps, not page fault.
  523                  */
  524                 KASSERT(tf->tf_tstate & TSTATE_PRIV,
  525                     ("trap_pfault: fault on nucleus context from user mode"));
  526 
  527                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
  528                     tf->tf_tpc <= (u_long)copy_nofault_end) {
  529                         vm_map_lock_read(kernel_map);
  530                         if (vm_map_lookup_entry(kernel_map, va, &entry) &&
  531                             (entry->eflags & MAP_ENTRY_NOFAULT) != 0) {
  532                                 tf->tf_tpc = (u_long)copy_fault;
  533                                 tf->tf_tnpc = tf->tf_tpc + 4;
  534                                 vm_map_unlock_read(kernel_map);
  535                                 return (0);
  536                         }
  537                         vm_map_unlock_read(kernel_map);
  538                 }
  539 
  540                 /*
  541                  * We don't have to worry about process locking or stacks in
  542                  * the kernel.
  543                  */
  544                 rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL);
  545         }
  546 
  547         CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
  548             td, va, rv);
  549         if (rv == KERN_SUCCESS)
  550                 return (0);
  551         if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
  552                 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
  553                     tf->tf_tpc <= (u_long)fs_nofault_end) {
  554                         tf->tf_tpc = (u_long)fs_fault;
  555                         tf->tf_tnpc = tf->tf_tpc + 4;
  556                         return (0);
  557                 }
  558                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
  559                     tf->tf_tpc <= (u_long)copy_nofault_end) {
  560                         tf->tf_tpc = (u_long)copy_fault;
  561                         tf->tf_tnpc = tf->tf_tpc + 4;
  562                         return (0);
  563                 }
  564         }
  565         return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
  566 }
  567 
  568 /* Maximum number of arguments that can be passed via the out registers. */
  569 #define REG_MAXARGS     6
  570 
  571 int
  572 cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
  573 {
  574         struct trapframe *tf;
  575         struct proc *p;
  576         register_t *argp;
  577         int reg;
  578         int regcnt;
  579         int error;
  580 
  581         p = td->td_proc;
  582         tf = td->td_frame;
  583         reg = 0;
  584         regcnt = REG_MAXARGS;
  585 
  586         sa->code = tf->tf_global[1];
  587 
  588         if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
  589                 sa->code = tf->tf_out[reg++];
  590                 regcnt--;
  591         }
  592 
  593         if (p->p_sysent->sv_mask)
  594                 sa->code &= p->p_sysent->sv_mask;
  595         if (sa->code >= p->p_sysent->sv_size)
  596                 sa->callp = &p->p_sysent->sv_table[0];
  597         else
  598                 sa->callp = &p->p_sysent->sv_table[sa->code];
  599 
  600         sa->narg = sa->callp->sy_narg;
  601         KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
  602             ("Too many syscall arguments!"));
  603         error = 0;
  604         argp = sa->args;
  605         bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
  606         if (sa->narg > regcnt)
  607                 error = copyin((void *)(tf->tf_out[6] + SPOFF +
  608                     offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
  609                     (sa->narg - regcnt) * sizeof(sa->args[0]));
  610         if (error == 0) {
  611                 td->td_retval[0] = 0;
  612                 td->td_retval[1] = 0;
  613         }
  614 
  615         return (error);
  616 }
  617 
  618 #include "../../kern/subr_syscall.c"
  619 
  620 /*
  621  * Syscall handler
  622  * The arguments to the syscall are passed in the out registers by the caller,
  623  * and are saved in the trap frame.  The syscall number is passed in %g1 (and
  624  * also saved in the trap frame).
  625  */
  626 void
  627 syscall(struct trapframe *tf)
  628 {
  629         struct thread *td;
  630         struct syscall_args sa;
  631         int error;
  632 
  633         td = curthread;
  634         td->td_frame = tf;
  635 
  636         KASSERT(td != NULL, ("trap: curthread NULL"));
  637         KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
  638 
  639         /*
  640          * For syscalls, we don't want to retry the faulting instruction
  641          * (usually), instead we need to advance one instruction.
  642          */
  643         td->td_pcb->pcb_tpc = tf->tf_tpc;
  644         TF_DONE(tf);
  645 
  646         error = syscallenter(td, &sa);
  647         syscallret(td, error, &sa);
  648 }

Cache object: 29c087b744db84bbd87ebc8a3b97db90


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