Messages in this thread | | | Date | Tue, 23 Aug 2005 13:54:56 -0400 | From | Chuck Ebbert <> | Subject | Re: [patch 2.6.13-rc6] i386: fix incorrect FP signal delivery |
| |
On Tue, 23 Aug 2005 02:20:07 +0200, Andi Kleen wrote:
> every reviewer has to look up all the bits in the manual?
I fixed the test program too:
Before patch:
$ ./fpsig handler: signum = 8, errno = 0, code = 0 [unknown] handler: fpu cwd = 0xb40, fpu swd = 0xbaa0 handler: i387 unmasked precision exception, rounded up
After:
$ ./fpsig handler: signum = 8, errno = 0, code = 6 [inexact result] handler: fpu cwd = 0xb40, fpu swd = 0xbaa0 handler: i387 unmasked precision exception, rounded up
/* i387 fp signal test */
#define _GNU_SOURCE #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <signal.h> #include <errno.h>
__attribute__ ((aligned(4096))) unsigned char altstack[4096]; unsigned short cw = 0x0b40; /* unmask all exceptions, round up */ struct sigaction sa; stack_t ss = { .ss_sp = &altstack[2047], .ss_size = sizeof(altstack)/2, };
static void handler(int nr, siginfo_t *si, void *uc) { char *decode; int code = si->si_code; unsigned short cwd = *(unsigned short *)&altstack[0xd84]; unsigned short swd = *(unsigned short *)&altstack[0xd88];
switch (code) { case FPE_INTDIV: decode = "divide by zero"; break; case FPE_FLTRES: decode = "inexact result"; break; case FPE_FLTINV: decode = "invalid operation"; break; default: decode = "unknown"; break; } printf("handler: signum = %d, errno = %d, code = %d [%s]\n", si->si_signo, si->si_errno, code, decode); printf("handler: fpu cwd = 0x%hx, fpu swd = 0x%hx\n", cwd, swd); if (swd & 0x20 & ~cwd) printf("handler: i387 unmasked precision exception, rounded %s\n", swd & 0x200 ? "up" : "down"); exit(1); }
int main(int argc, char * const argv[]) { sa.sa_sigaction = handler; sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
if (sigaltstack(&ss, 0)) perror("sigaltstack"); if (sigaction(SIGFPE, &sa, NULL)) perror("sigaction");
asm volatile ("fnclex ; fldcw %0" : : "m" (cw)); asm volatile ( /* st(1) = 3.0, st = 1.0 */ "fld1 ; fld1 ; faddp ; fld1 ; faddp ; fld1"); asm volatile ( "fdivp ; fwait"); /* 1.0 / 3.0 */
return 0; } __ Chuck - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |