diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2004-10-28 20:36:16 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2004-10-28 20:36:16 +0000 |
commit | e636cc4e77b148deac7c592098b8c46c682edbd7 (patch) | |
tree | a59a6c072f840e84d5d048365e528640b53f12df /sys | |
parent | 18052f748f5bdae3b6b3b241a69d2060d32bd82a (diff) |
SIGFPE signal codes.
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/fpu.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c index 1f157665fc5..820fb7a8305 100644 --- a/sys/arch/amd64/amd64/fpu.c +++ b/sys/arch/amd64/amd64/fpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpu.c,v 1.6 2004/07/11 11:31:57 kettenis Exp $ */ +/* $OpenBSD: fpu.c,v 1.7 2004/10/28 20:36:15 kettenis Exp $ */ /* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /*- @@ -95,6 +95,7 @@ #define stts() lcr0(rcr0() | CR0_TS) void fpudna(struct cpu_info *); +static int x86fpflags_to_siginfo(u_int32_t); /* * Init the FPU. @@ -120,7 +121,9 @@ fputrap(struct trapframe *frame) { struct proc *p = curcpu()->ci_fpcurproc; struct savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; + u_int32_t statbits; u_int16_t cw; + int code; union sigval sv; #ifdef DIAGNOSTIC @@ -134,21 +137,46 @@ fputrap(struct trapframe *frame) fxsave(sfp); if (frame->tf_trapno == T_XMM) { + statbits = sfp->fp_fxsave.fx_mxcsr; } else { fninit(); fwait(); cw = sfp->fp_fxsave.fx_fcw; fldcw(&cw); fwait(); + statbits = sfp->fp_fxsave.fx_fsw; } sfp->fp_ex_tw = sfp->fp_fxsave.fx_ftw; sfp->fp_ex_sw = sfp->fp_fxsave.fx_fsw; + code = x86fpflags_to_siginfo (statbits); sv.sival_ptr = (void *)frame->tf_rip; /* XXX - ? */ KERNEL_PROC_LOCK(p); - trapsignal(p, SIGFPE, frame->tf_err, 0 /* XXX */, sv); + trapsignal(p, SIGFPE, frame->tf_err, code, sv); KERNEL_PROC_UNLOCK(p); } +static int +x86fpflags_to_siginfo(u_int32_t flags) +{ + int i; + static int x86fp_siginfo_table[] = { + FPE_FLTINV, /* bit 0 - invalid operation */ + FPE_FLTRES, /* bit 1 - denormal operand */ + FPE_FLTDIV, /* bit 2 - divide by zero */ + FPE_FLTOVF, /* bit 3 - fp overflow */ + FPE_FLTUND, /* bit 4 - fp underflow */ + FPE_FLTRES, /* bit 5 - fp precision */ + FPE_FLTINV, /* bit 6 - stack fault */ + }; + + for (i=0;i < sizeof(x86fp_siginfo_table)/sizeof(int); i++) { + if (flags & (1 << i)) + return (x86fp_siginfo_table[i]); + } + /* punt if flags not set */ + return (FPE_FLTINV); +} + /* * Implement device not available (DNA) exception * |