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

Cache object: 64955fb54dcf0956c1fdb92b94fdbf44


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