The following reply was made to PR amd64/169927; it has been noted by GNATS.

From: Konstantin Belousov <[email protected]>
To: Bruce Evans <[email protected]>
Cc: Ed Alley <[email protected]>, [email protected],
        [email protected]
Subject: Re: amd64/169927: siginfo, si_code for fpe errors when error occurs 
using the SSE math processor
Date: Tue, 17 Jul 2012 16:44:26 +0300

 --IJFRpmOek+ZRSQoz
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 It was on my TODO list for long time. Lets handle amd64 first, both for
 native and compat32.
 
 I think the following should be somewhat better variant. I do leave
 the fnclex there for x87.
 
 diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
 index a7812b7..34cf8d4 100644
 --- a/sys/amd64/amd64/fpu.c
 +++ b/sys/amd64/amd64/fpu.c
 @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
  #define       fxrstor(addr)           __asm __volatile("fxrstor %0" : : "m" 
(*(addr)))
  #define       fxsave(addr)            __asm __volatile("fxsave %0" : "=3Dm" 
(*(addr)))
  #define       ldmxcsr(csr)            __asm __volatile("ldmxcsr %0" : : "m" 
(csr))
 +#define       stmxcsr(addr)           __asm __volatile("stmxcsr %0" : : "m" 
(*(addr)))
 =20
  static __inline void
  xrstor(char *addr, uint64_t mask)
 @@ -105,6 +106,7 @@ void       fnstsw(caddr_t addr);
  void  fxsave(caddr_t addr);
  void  fxrstor(caddr_t addr);
  void  ldmxcsr(u_int csr);
 +void  stmxcsr(u_int csr);
  void  xrstor(char *addr, uint64_t mask);
  void  xsave(char *addr, uint64_t mask);
 =20
 @@ -113,9 +115,6 @@ void       xsave(char *addr, uint64_t mask);
  #define       start_emulating()       load_cr0(rcr0() | CR0_TS)
  #define       stop_emulating()        clts()
 =20
 -#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) =3D=3D 512);
  CTASSERT(sizeof(struct xstate_hdr) =3D=3D 64);
  CTASSERT(sizeof(struct savefpu_ymm) =3D=3D 832);
 @@ -514,11 +513,15 @@ static char fpetable[128] =3D {
  };
 =20
  /*
 - * Preserve the FP status word, clear FP exceptions, then generate a SIGFP=
 E.
 + * 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
 @@ -531,8 +534,9 @@ static char fpetable[128] =3D {
   * solution for signals other than SIGFPE.
   */
  int
 -fputrap()
 +fputrap_x87(void)
  {
 +      struct savefpu *pcb_save;
        u_short control, status;
 =20
        critical_enter();
 @@ -543,19 +547,43 @@ fputrap()
         * wherever they are.
         */
        if (PCPU_GET(fpcurthread) !=3D curthread) {
 -              control =3D GET_FPU_CW(curthread);
 -              status =3D GET_FPU_SW(curthread);
 +              pcb_save =3D curthread->td_pcb->pcb_save;
 +              control =3D pcb_save->sv_env.en_cw;
 +              status =3D pcb_save->sv_env.en_sw;
        } else {
                fnstcw(&control);
                fnstsw(&status);
 +              fnclex();
        }
 =20
 -      if (PCPU_GET(fpcurthread) =3D=3D curthread)
 -              fnclex();
        critical_exit();
        return (fpetable[status & ((~control & 0x3f) | 0x40)]);
  }
 =20
 +int
 +fputrap_sse(void)
 +{
 +      u_int mxcsr;
 +      u_short control, status;
 +
 +      critical_enter();
 +
 +      /*
 +       * Coomparing with the x87 #MF handler, we do not clear
 +       * exceptions from the mxcsr.
 +       */
 +      if (PCPU_GET(fpcurthread) !=3D curthread)
 +              mxcsr =3D curthread->td_pcb->pcb_save->sv_env.en_mxcsr;
 +      else
 +              stmxcsr(&mxcsr);
 +
 +      critical_exit();
 +
 +      status =3D mxcsr & 0x3f;
 +      control =3D (mxcsr >> 16) & 0x3f;
 +      return (fpetable[status & (~control | 0x40)]);
 +}
 +
  /*
   * Implement device not available (DNA) exception
   *
 diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
 index 75e15e0..57d1cc2 100644
 --- a/sys/amd64/amd64/trap.c
 +++ b/sys/amd64/amd64/trap.c
 @@ -328,7 +328,7 @@ trap(struct trapframe *frame)
                        break;
 =20
                case T_ARITHTRAP:       /* arithmetic trap */
 -                      ucode =3D fputrap();
 +                      ucode =3D fputrap_x87();
                        if (ucode =3D=3D -1)
                                goto userout;
                        i =3D SIGFPE;
 @@ -442,7 +442,9 @@ trap(struct trapframe *frame)
                        break;
 =20
                case T_XMMFLT:          /* SIMD floating-point exception */
 -                      ucode =3D 0; /* XXX */
 +                      ucode =3D fputrap_sse();
 +                      if (ucode =3D=3D -1)
 +                              goto userout;
                        i =3D SIGFPE;
                        break;
                }
 diff --git a/sys/amd64/include/fpu.h b/sys/amd64/include/fpu.h
 index 98a016b..7d0f0ea 100644
 --- a/sys/amd64/include/fpu.h
 +++ b/sys/amd64/include/fpu.h
 @@ -62,7 +62,8 @@ int  fpusetregs(struct thread *td, struct savefpu *addr,
            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);
 
 --IJFRpmOek+ZRSQoz
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (FreeBSD)
 
 iEYEARECAAYFAlAFbDkACgkQC3+MBN1Mb4gPfgCeI7OF9u6tfuHgPoVp/bUfG1kc
 iksAn1q9GtduJNGtll0dZd2X336LRijE
 =kkdY
 -----END PGP SIGNATURE-----
 
 --IJFRpmOek+ZRSQoz--
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-amd64
To unsubscribe, send any mail to "[email protected]"

Reply via email to