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/powerpc/powerpc/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) 1995, 1996 Wolfgang Solfrank.
    3  * Copyright (C) 1995, 1996 TooLs GmbH.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    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  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by TooLs GmbH.
   17  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/7.4/sys/powerpc/powerpc/trap.c 189498 2009-03-07 20:39:42Z nwhitehorn $");
   36 
   37 #include "opt_ktrace.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/kdb.h>
   41 #include <sys/proc.h>
   42 #include <sys/ktr.h>
   43 #include <sys/lock.h>
   44 #include <sys/mutex.h>
   45 #include <sys/pioctl.h>
   46 #include <sys/ptrace.h>
   47 #include <sys/reboot.h>
   48 #include <sys/syscall.h>
   49 #include <sys/sysent.h>
   50 #include <sys/systm.h>
   51 #include <sys/uio.h>
   52 #include <sys/signalvar.h>
   53 #ifdef KTRACE
   54 #include <sys/ktrace.h>
   55 #endif
   56 #include <sys/vmmeter.h>
   57 
   58 #include <security/audit/audit.h>
   59 
   60 #include <vm/vm.h>
   61 #include <vm/pmap.h>
   62 #include <vm/vm_extern.h>
   63 #include <vm/vm_param.h>
   64 #include <vm/vm_kern.h>
   65 #include <vm/vm_map.h>
   66 #include <vm/vm_page.h>
   67 
   68 #include <machine/altivec.h>
   69 #include <machine/cpu.h>
   70 #include <machine/db_machdep.h>
   71 #include <machine/fpu.h>
   72 #include <machine/frame.h>
   73 #include <machine/pcb.h>
   74 #include <machine/pmap.h>
   75 #include <machine/psl.h>
   76 #include <machine/trap.h>
   77 #include <machine/spr.h>
   78 #include <machine/sr.h>
   79 
   80 static void     trap_fatal(struct trapframe *frame);
   81 static void     printtrap(u_int vector, struct trapframe *frame, int isfatal,
   82                     int user);
   83 static int      trap_pfault(struct trapframe *frame, int user);
   84 static int      fix_unaligned(struct thread *td, struct trapframe *frame);
   85 static int      handle_onfault(struct trapframe *frame);
   86 static void     syscall(struct trapframe *frame);
   87 
   88 static __inline void    setusr(u_int);
   89 
   90 int     setfault(faultbuf);             /* defined in locore.S */
   91 
   92 /* Why are these not defined in a header? */
   93 int     badaddr(void *, size_t);
   94 int     badaddr_read(void *, size_t, int *);
   95 
   96 extern char     *syscallnames[];
   97 
   98 struct powerpc_exception {
   99         u_int   vector;
  100         char    *name;
  101 };
  102 
  103 static struct powerpc_exception powerpc_exceptions[] = {
  104         { 0x0100, "system reset" },
  105         { 0x0200, "machine check" },
  106         { 0x0300, "data storage interrupt" },
  107         { 0x0400, "instruction storage interrupt" },
  108         { 0x0500, "external interrupt" },
  109         { 0x0600, "alignment" },
  110         { 0x0700, "program" },
  111         { 0x0800, "floating-point unavailable" },
  112         { 0x0900, "decrementer" },
  113         { 0x0c00, "system call" },
  114         { 0x0d00, "trace" },
  115         { 0x0e00, "floating-point assist" },
  116         { 0x0f00, "performance monitoring" },
  117         { 0x0f20, "altivec unavailable" },
  118         { 0x1000, "instruction tlb miss" },
  119         { 0x1100, "data load tlb miss" },
  120         { 0x1200, "data store tlb miss" },
  121         { 0x1300, "instruction breakpoint" },
  122         { 0x1400, "system management" },
  123         { 0x1600, "altivec assist" },
  124         { 0x1700, "thermal management" },
  125         { 0x2000, "run mode/trace" },
  126         { 0x3000, NULL }
  127 };
  128 
  129 static const char *
  130 trapname(u_int vector)
  131 {
  132         struct  powerpc_exception *pe;
  133 
  134         for (pe = powerpc_exceptions; pe->vector != 0x3000; pe++) {
  135                 if (pe->vector == vector)
  136                         return (pe->name);
  137         }
  138 
  139         return ("unknown");
  140 }
  141 
  142 void
  143 trap(struct trapframe *frame)
  144 {
  145         struct thread   *td;
  146         struct proc     *p;
  147         int             sig, type, user;
  148         u_int           ucode;
  149         ksiginfo_t      ksi;
  150 
  151         PCPU_INC(cnt.v_trap);
  152 
  153         td = PCPU_GET(curthread);
  154         p = td->td_proc;
  155 
  156         type = ucode = frame->exc;
  157         sig = 0;
  158         user = frame->srr1 & PSL_PR;
  159 
  160         CTR3(KTR_TRAP, "trap: %s type=%s (%s)", p->p_comm,
  161             trapname(type), user ? "user" : "kernel");
  162 
  163         if (user) {
  164                 td->td_pticks = 0;
  165                 td->td_frame = frame;
  166                 if (td->td_ucred != p->p_ucred)
  167                         cred_update_thread(td);
  168 
  169                 /* User Mode Traps */
  170                 switch (type) {
  171                 case EXC_RUNMODETRC:
  172                 case EXC_TRC:
  173                         frame->srr1 &= ~PSL_SE;
  174                         sig = SIGTRAP;
  175                         break;
  176 
  177                 case EXC_DSI:
  178                 case EXC_ISI:
  179                         sig = trap_pfault(frame, 1);
  180                         break;
  181 
  182                 case EXC_SC:
  183                         syscall(frame);
  184                         break;
  185 
  186                 case EXC_FPU:
  187                         KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU,
  188                             ("FPU already enabled for thread"));
  189                         enable_fpu(td);
  190                         break;
  191 
  192                 case EXC_VEC:
  193                         KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC,
  194                             ("Altivec already enabled for thread"));
  195                         enable_vec(td);
  196                         break;
  197 
  198                 case EXC_VECAST:
  199                         printf("Vector assist exception!\n");
  200                         sig = SIGILL;
  201                         break;
  202 
  203                 case EXC_ALI:
  204                         if (fix_unaligned(td, frame) != 0)
  205                                 sig = SIGBUS;
  206                         else
  207                                 frame->srr0 += 4;
  208                         break;
  209 
  210                 case EXC_PGM:
  211                         /* XXX temporarily */
  212                         /* XXX: Magic Number? */
  213                         if (frame->srr1 & 0x0002000)
  214                                 sig = SIGTRAP;
  215                         else
  216                                 sig = SIGILL;
  217                         break;
  218 
  219                 default:
  220                         trap_fatal(frame);
  221                 }
  222         } else {
  223                 /* Kernel Mode Traps */
  224 
  225                 KASSERT(cold || td->td_ucred != NULL,
  226                     ("kernel trap doesn't have ucred"));
  227                 switch (type) {
  228                 case EXC_DSI:
  229                         if (trap_pfault(frame, 0) == 0)
  230                                 return;
  231                         break;
  232                 case EXC_MCHK:
  233                         if (handle_onfault(frame))
  234                                 return;
  235                         break;
  236                 default:
  237                         break;
  238                 }
  239                 trap_fatal(frame);
  240         }
  241 
  242 #ifdef  ALTIVEC
  243         if (td != PCPU_GET(vecthread) ||
  244             td->td_pcb->pcb_veccpu != PCPU_GET(cpuid))
  245                 frame->srr1 &= ~PSL_VEC;
  246 #endif /* ALTIVEC */
  247 
  248         if (sig != 0) {
  249                 if (p->p_sysent->sv_transtrap != NULL)
  250                         sig = (p->p_sysent->sv_transtrap)(sig, type);
  251                 ksiginfo_init_trap(&ksi);
  252                 ksi.ksi_signo = sig;
  253                 ksi.ksi_code = (int) ucode; /* XXX, not POSIX */
  254                 /* ksi.ksi_addr = ? */
  255                 ksi.ksi_trapno = type;
  256                 trapsignal(td, &ksi);
  257         }
  258 
  259         userret(td, frame);
  260         mtx_assert(&Giant, MA_NOTOWNED);
  261 }
  262 
  263 static void
  264 trap_fatal(struct trapframe *frame)
  265 {
  266 
  267         printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
  268 #ifdef KDB
  269         if ((debugger_on_panic || kdb_active) &&
  270             kdb_trap(frame->exc, 0, frame))
  271                 return;
  272 #endif
  273         panic("%s trap", trapname(frame->exc));
  274 }
  275 
  276 static void
  277 printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
  278 {
  279 
  280         printf("\n");
  281         printf("%s %s trap:\n", isfatal ? "fatal" : "handled",
  282             user ? "user" : "kernel");
  283         printf("\n");
  284         printf("   exception       = 0x%x (%s)\n", vector >> 8,
  285             trapname(vector));
  286         switch (vector) {
  287         case EXC_DSI:
  288                 printf("   virtual address = 0x%x\n", frame->dar);
  289                 break;
  290         case EXC_ISI:
  291                 printf("   virtual address = 0x%x\n", frame->srr0);
  292                 break;
  293         }
  294         printf("   srr0            = 0x%x\n", frame->srr0);
  295         printf("   srr1            = 0x%x\n", frame->srr1);
  296         printf("   curthread       = %p\n", curthread);
  297         if (curthread != NULL)
  298                 printf("          pid = %d, comm = %s\n",
  299                     curthread->td_proc->p_pid, curthread->td_proc->p_comm);
  300         printf("\n");
  301 }
  302 
  303 /*
  304  * Handles a fatal fault when we have onfault state to recover.  Returns
  305  * non-zero if there was onfault recovery state available.
  306  */
  307 static int
  308 handle_onfault(struct trapframe *frame)
  309 {
  310         struct          thread *td;
  311         faultbuf        *fb;
  312 
  313         td = curthread;
  314         fb = td->td_pcb->pcb_onfault;
  315         if (fb != NULL) {
  316                 frame->srr0 = (*fb)[0];
  317                 frame->fixreg[1] = (*fb)[1];
  318                 frame->fixreg[2] = (*fb)[2];
  319                 frame->fixreg[3] = 1;
  320                 frame->cr = (*fb)[3];
  321                 bcopy(&(*fb)[4], &frame->fixreg[13],
  322                     19 * sizeof(register_t));
  323                 return (1);
  324         }
  325         return (0);
  326 }
  327 
  328 void
  329 syscall(struct trapframe *frame)
  330 {
  331         caddr_t         params;
  332         struct          sysent *callp;
  333         struct          thread *td;
  334         struct          proc *p;
  335         int             error, n;
  336         size_t          narg;
  337         register_t      args[10];
  338         u_int           code;
  339 
  340         td = PCPU_GET(curthread);
  341         p = td->td_proc;
  342 
  343         PCPU_INC(cnt.v_syscall);
  344 
  345 #ifdef KSE
  346         if (p->p_flag & P_SA)
  347                 thread_user_enter(td);
  348 #endif
  349 
  350         code = frame->fixreg[0];
  351         params = (caddr_t)(frame->fixreg + FIRSTARG);
  352         n = NARGREG;
  353 
  354         if (p->p_sysent->sv_prepsyscall) {
  355                 /*
  356                  * The prep code is MP aware.
  357                  */
  358                 (*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
  359         } else if (code == SYS_syscall) {
  360                 /*
  361                  * code is first argument,
  362                  * followed by actual args.
  363                  */
  364                 code = *(u_int *) params;
  365                 params += sizeof(register_t);
  366                 n -= 1;
  367         } else if (code == SYS___syscall) {
  368                 /*
  369                  * Like syscall, but code is a quad,
  370                  * so as to maintain quad alignment
  371                  * for the rest of the args.
  372                  */
  373                 params += sizeof(register_t);
  374                 code = *(u_int *) params;
  375                 params += sizeof(register_t);
  376                 n -= 2;
  377         }
  378 
  379         if (p->p_sysent->sv_mask)
  380                 code &= p->p_sysent->sv_mask;
  381 
  382         if (code >= p->p_sysent->sv_size)
  383                 callp = &p->p_sysent->sv_table[0];
  384         else
  385                 callp = &p->p_sysent->sv_table[code];
  386 
  387         narg = callp->sy_narg;
  388 
  389         if (narg > n) {
  390                 bcopy(params, args, n * sizeof(register_t));
  391                 error = copyin(MOREARGS(frame->fixreg[1]), args + n,
  392                                (narg - n) * sizeof(register_t));
  393                 params = (caddr_t)args;
  394         } else
  395                 error = 0;
  396 
  397         CTR5(KTR_SYSC, "syscall: p=%s %s(%x %x %x)", p->p_comm,
  398              syscallnames[code],
  399              frame->fixreg[FIRSTARG],
  400              frame->fixreg[FIRSTARG+1],
  401              frame->fixreg[FIRSTARG+2]);
  402 
  403 #ifdef  KTRACE
  404         if (KTRPOINT(td, KTR_SYSCALL))
  405                 ktrsyscall(code, narg, (register_t *)params);
  406 #endif
  407 
  408         td->td_syscalls++;
  409 
  410         if (error == 0) {
  411                 td->td_retval[0] = 0;
  412                 td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
  413 
  414                 STOPEVENT(p, S_SCE, narg);
  415 
  416                 PTRACESTOP_SC(p, td, S_PT_SCE);
  417 
  418                 AUDIT_SYSCALL_ENTER(code, td);
  419                 error = (*callp->sy_call)(td, params);
  420                 AUDIT_SYSCALL_EXIT(error, td);
  421 
  422                 CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", p->p_comm,
  423                      syscallnames[code], td->td_retval[0]);
  424         }
  425         switch (error) {
  426         case 0:
  427                 if (frame->fixreg[0] == SYS___syscall &&
  428                     code != SYS_freebsd6_lseek && code != SYS_lseek) {
  429                         /*
  430                          * 64-bit return, 32-bit syscall. Fixup byte order
  431                          */
  432                         frame->fixreg[FIRSTARG] = 0;
  433                         frame->fixreg[FIRSTARG + 1] = td->td_retval[0];
  434                 } else {
  435                         frame->fixreg[FIRSTARG] = td->td_retval[0];
  436                         frame->fixreg[FIRSTARG + 1] = td->td_retval[1];
  437                 }
  438                 /* XXX: Magic number */
  439                 frame->cr &= ~0x10000000;
  440                 break;
  441         case ERESTART:
  442                 /*
  443                  * Set user's pc back to redo the system call.
  444                  */
  445                 frame->srr0 -= 4;
  446                 break;
  447         case EJUSTRETURN:
  448                 /* nothing to do */
  449                 break;
  450         default:
  451                 if (p->p_sysent->sv_errsize) {
  452                         if (error >= p->p_sysent->sv_errsize)
  453                                 error = -1;     /* XXX */
  454                         else
  455                                 error = p->p_sysent->sv_errtbl[error];
  456                 }
  457                 frame->fixreg[FIRSTARG] = error;
  458                 /* XXX: Magic number: Carry Flag Equivalent? */
  459                 frame->cr |= 0x10000000;
  460                 break;
  461         }
  462 
  463         /*
  464          * Check for misbehavior.
  465          */
  466         WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
  467             (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
  468         KASSERT(td->td_critnest == 0,
  469             ("System call %s returning in a critical section",
  470             (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
  471         KASSERT(td->td_locks == 0,
  472             ("System call %s returning with %d locks held",
  473             (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
  474             td->td_locks));
  475 
  476 #ifdef  KTRACE
  477         if (KTRPOINT(td, KTR_SYSRET))
  478                 ktrsysret(code, error, td->td_retval[0]);
  479 #endif
  480 
  481         /*
  482          * Does the comment in the i386 code about errno apply here?
  483          */
  484         STOPEVENT(p, S_SCX, code);
  485  
  486         PTRACESTOP_SC(p, td, S_PT_SCX);
  487 }
  488 
  489 static int
  490 trap_pfault(struct trapframe *frame, int user)
  491 {
  492         vm_offset_t     eva, va;
  493         struct          thread *td;
  494         struct          proc *p;
  495         vm_map_t        map;
  496         vm_prot_t       ftype;
  497         int             rv;
  498         u_int           user_sr;
  499 
  500         td = curthread;
  501         p = td->td_proc;
  502         if (frame->exc == EXC_ISI) {
  503                 eva = frame->srr0;
  504                 ftype = VM_PROT_READ | VM_PROT_EXECUTE;
  505         } else {
  506                 eva = frame->dar;
  507                 if (frame->dsisr & DSISR_STORE)
  508                         ftype = VM_PROT_WRITE;
  509                 else
  510                         ftype = VM_PROT_READ;
  511         }
  512 
  513         if (user) {
  514                 map = &p->p_vmspace->vm_map;
  515         } else {
  516                 if ((eva >> ADDR_SR_SHFT) == USER_SR) {
  517                         if (p->p_vmspace == NULL)
  518                                 return (SIGSEGV);
  519 
  520                         __asm ("mfsr %0, %1"
  521                             : "=r"(user_sr)
  522                             : "K"(USER_SR));
  523                         eva &= ADDR_PIDX | ADDR_POFF;
  524                         eva |= user_sr << ADDR_SR_SHFT;
  525                         map = &p->p_vmspace->vm_map;
  526                 } else {
  527                         map = kernel_map;
  528                 }
  529         }
  530         va = trunc_page(eva);
  531 
  532         if (map != kernel_map) {
  533                 /*
  534                  * Keep swapout from messing with us during this
  535                  *      critical time.
  536                  */
  537                 PROC_LOCK(p);
  538                 ++p->p_lock;
  539                 PROC_UNLOCK(p);
  540 
  541                 /* Fault in the user page: */
  542                 rv = vm_fault(map, va, ftype,
  543                       (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY
  544                                               : VM_FAULT_NORMAL);
  545 
  546                 PROC_LOCK(p);
  547                 --p->p_lock;
  548                 PROC_UNLOCK(p);
  549         } else {
  550                 /*
  551                  * Don't have to worry about process locking or stacks in the
  552                  * kernel.
  553                  */
  554                 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
  555         }
  556 
  557         if (rv == KERN_SUCCESS)
  558                 return (0);
  559 
  560         if (!user && handle_onfault(frame))
  561                 return (0);
  562 
  563         return (SIGSEGV);
  564 }
  565 
  566 static __inline void
  567 setusr(u_int content)
  568 {
  569         __asm __volatile ("isync; mtsr %0,%1; isync"
  570                       :: "n"(USER_SR), "r"(content));
  571 }
  572 
  573 int
  574 badaddr(void *addr, size_t size)
  575 {
  576         return (badaddr_read(addr, size, NULL));
  577 }
  578 
  579 int
  580 badaddr_read(void *addr, size_t size, int *rptr)
  581 {
  582         struct thread   *td;
  583         faultbuf        env;
  584         int             x;
  585 
  586         /* Get rid of any stale machine checks that have been waiting.  */
  587         __asm __volatile ("sync; isync");
  588 
  589         td = PCPU_GET(curthread);
  590 
  591         if (setfault(env)) {
  592                 td->td_pcb->pcb_onfault = 0;
  593                 __asm __volatile ("sync");
  594                 return 1;
  595         }
  596 
  597         __asm __volatile ("sync");
  598 
  599         switch (size) {
  600         case 1:
  601                 x = *(volatile int8_t *)addr;
  602                 break;
  603         case 2:
  604                 x = *(volatile int16_t *)addr;
  605                 break;
  606         case 4:
  607                 x = *(volatile int32_t *)addr;
  608                 break;
  609         default:
  610                 panic("badaddr: invalid size (%d)", size);
  611         }
  612 
  613         /* Make sure we took the machine check, if we caused one. */
  614         __asm __volatile ("sync; isync");
  615 
  616         td->td_pcb->pcb_onfault = 0;
  617         __asm __volatile ("sync");      /* To be sure. */
  618 
  619         /* Use the value to avoid reorder. */
  620         if (rptr)
  621                 *rptr = x;
  622 
  623         return (0);
  624 }
  625 
  626 /*
  627  * For now, this only deals with the particular unaligned access case
  628  * that gcc tends to generate.  Eventually it should handle all of the
  629  * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
  630  */
  631 
  632 static int
  633 fix_unaligned(struct thread *td, struct trapframe *frame)
  634 {
  635         struct thread   *fputhread;
  636         int             indicator, reg;
  637         double          *fpr;
  638 
  639         indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr);
  640 
  641         switch (indicator) {
  642         case EXC_ALI_LFD:
  643         case EXC_ALI_STFD:
  644                 reg = EXC_ALI_RST(frame->dsisr);
  645                 fpr = &td->td_pcb->pcb_fpu.fpr[reg];
  646                 fputhread = PCPU_GET(fputhread);
  647 
  648                 /* Juggle the FPU to ensure that we've initialized
  649                  * the FPRs, and that their current state is in
  650                  * the PCB.
  651                  */
  652                 if (fputhread != td) {
  653                         if (fputhread)
  654                                 save_fpu(fputhread);
  655                         enable_fpu(td);
  656                 }
  657                 save_fpu(td);
  658 
  659                 if (indicator == EXC_ALI_LFD) {
  660                         if (copyin((void *)frame->dar, fpr,
  661                             sizeof(double)) != 0)
  662                                 return -1;
  663                         enable_fpu(td);
  664                 } else {
  665                         if (copyout(fpr, (void *)frame->dar,
  666                             sizeof(double)) != 0)
  667                                 return -1;
  668                 }
  669                 return 0;
  670                 break;
  671         }
  672 
  673         return -1;
  674 }

Cache object: 42d6e91e228d4dee906b5d85c7c8002d


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