Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Jul 2012 13:50:10 GMT
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        freebsd-amd64@FreeBSD.org
Subject:   Re: amd64/169927: siginfo, si_code for fpe errors when error occurs using the SSE math processor
Message-ID:  <201207171350.q6HDoAJS033797@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR amd64/169927; it has been noted by GNATS.

From: Konstantin Belousov <kostikbel@gmail.com>
To: Bruce Evans <brde@optusnet.com.au>
Cc: Ed Alley <wea@llnl.gov>, freebsd-gnats-submit@freebsd.org,
        freebsd-amd64@freebsd.org
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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207171350.q6HDoAJS033797>