Author: kib
Date: Wed Jul 18 15:43:47 2012
New Revision: 238598
URL: http://svn.freebsd.org/changeset/base/238598

Log:
  On AMD64, provide siginfo.si_code for floating point errors when error
  occurs using the SSE math processor.  Update comments describing the
  handling of the exception status bits in coprocessors control words.
  
  Remove GET_FPU_CW and GET_FPU_SW macros which were used only once.
  Prefer to use curpcb to access pcb_save over the longer path of
  referencing pcb through the thread structure.
  
  Based on the submission by:   Ed Alley <wea llnl gov>
  PR:     amd64/169927
  Reviewed by:  bde
  MFC after:    3 weeks

Modified:
  head/sys/amd64/amd64/fpu.c
  head/sys/amd64/amd64/trap.c
  head/sys/amd64/include/fpu.h

Modified: head/sys/amd64/amd64/fpu.c
==============================================================================
--- head/sys/amd64/amd64/fpu.c  Wed Jul 18 15:36:03 2012        (r238597)
+++ head/sys/amd64/amd64/fpu.c  Wed Jul 18 15:43:47 2012        (r238598)
@@ -115,9 +115,6 @@ void        xsave(char *addr, uint64_t mask);
 #define        start_emulating()       load_cr0(rcr0() | CR0_TS)
 #define        stop_emulating()        clts()
 
-#define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_cw)
-#define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_sw)
-
 CTASSERT(sizeof(struct savefpu) == 512);
 CTASSERT(sizeof(struct xstate_hdr) == 64);
 CTASSERT(sizeof(struct savefpu_ymm) == 832);
@@ -516,11 +513,15 @@ static char fpetable[128] = {
 };
 
 /*
- * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE.
+ * Preserve the FP status word, clear FP exceptions for x87, then
+ * generate a SIGFPE.
+ *
+ * Clearing exceptions was necessary mainly to avoid IRQ13 bugs and is
+ * engraved in our i386 ABI.  We now depend on longjmp() restoring a
+ * usable state.  Restoring the state or examining it might fail if we
+ * didn't clear exceptions.
  *
- * Clearing exceptions is necessary mainly to avoid IRQ13 bugs.  We now
- * depend on longjmp() restoring a usable state.  Restoring the state
- * or examining it might fail if we didn't clear exceptions.
+ * For SSE exceptions, the exceptions are not cleared.
  *
  * The error code chosen will be one of the FPE_... macros. It will be
  * sent as the second argument to old BSD-style signal handlers and as
@@ -533,8 +534,9 @@ static char fpetable[128] = {
  * solution for signals other than SIGFPE.
  */
 int
-fputrap()
+fputrap_x87(void)
 {
+       struct savefpu *pcb_save;
        u_short control, status;
 
        critical_enter();
@@ -545,19 +547,33 @@ fputrap()
         * wherever they are.
         */
        if (PCPU_GET(fpcurthread) != curthread) {
-               control = GET_FPU_CW(curthread);
-               status = GET_FPU_SW(curthread);
+               pcb_save = PCPU_GET(curpcb)->pcb_save;
+               control = pcb_save->sv_env.en_cw;
+               status = pcb_save->sv_env.en_sw;
        } else {
                fnstcw(&control);
                fnstsw(&status);
+               fnclex();
        }
 
-       if (PCPU_GET(fpcurthread) == curthread)
-               fnclex();
        critical_exit();
        return (fpetable[status & ((~control & 0x3f) | 0x40)]);
 }
 
+int
+fputrap_sse(void)
+{
+       u_int mxcsr;
+
+       critical_enter();
+       if (PCPU_GET(fpcurthread) != curthread)
+               mxcsr = PCPU_GET(curpcb)->pcb_save->sv_env.en_mxcsr;
+       else
+               stmxcsr(&mxcsr);
+       critical_exit();
+       return (fpetable[(mxcsr & (~mxcsr >> 7)) & 0x3f]);
+}
+
 /*
  * Implement device not available (DNA) exception
  *

Modified: head/sys/amd64/amd64/trap.c
==============================================================================
--- head/sys/amd64/amd64/trap.c Wed Jul 18 15:36:03 2012        (r238597)
+++ head/sys/amd64/amd64/trap.c Wed Jul 18 15:43:47 2012        (r238598)
@@ -328,7 +328,7 @@ trap(struct trapframe *frame)
                        break;
 
                case T_ARITHTRAP:       /* arithmetic trap */
-                       ucode = fputrap();
+                       ucode = fputrap_x87();
                        if (ucode == -1)
                                goto userout;
                        i = SIGFPE;
@@ -442,7 +442,9 @@ trap(struct trapframe *frame)
                        break;
 
                case T_XMMFLT:          /* SIMD floating-point exception */
-                       ucode = 0; /* XXX */
+                       ucode = fputrap_sse();
+                       if (ucode == -1)
+                               goto userout;
                        i = SIGFPE;
                        break;
                }

Modified: head/sys/amd64/include/fpu.h
==============================================================================
--- head/sys/amd64/include/fpu.h        Wed Jul 18 15:36:03 2012        
(r238597)
+++ head/sys/amd64/include/fpu.h        Wed Jul 18 15:43:47 2012        
(r238598)
@@ -62,7 +62,8 @@ int   fpusetregs(struct thread *td, struct
            char *xfpustate, size_t xfpustate_size);
 int    fpusetxstate(struct thread *td, char *xfpustate,
            size_t xfpustate_size);
-int    fputrap(void);
+int    fputrap_sse(void);
+int    fputrap_x87(void);
 void   fpuuserinited(struct thread *td);
 struct fpu_kern_ctx *fpu_kern_alloc_ctx(u_int flags);
 void   fpu_kern_free_ctx(struct fpu_kern_ctx *ctx);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to