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

Cache object: 317d95951ae36e41c107e7e3eb7c27f4


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