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

Cache object: 2343eeee9c0a354d4c488884f47ff0b3


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