diff options
author | Chuck Ebbert <76306.1226@compuserve.com> | 2005-08-23 21:36:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-23 19:52:37 -0700 |
commit | b1daec3089a129a67169d3ae975985a7480fe17f (patch) | |
tree | 874a99ec05afb39419f1e4ac0f90cf7c6a70e1fc /arch/i386/kernel/traps.c | |
parent | 11532cc6aa73a47023268d718bf43b646494615c (diff) | |
download | lwn-b1daec3089a129a67169d3ae975985a7480fe17f.tar.gz lwn-b1daec3089a129a67169d3ae975985a7480fe17f.zip |
[PATCH] i386: fix incorrect FP signal code
i386 floating-point exception handling has a bug that can cause error
code 0 to be sent instead of the proper code during signal delivery.
This is caused by unconditionally checking the IS and c1 bits from the
FPU status word when they are not always relevant. The IS bit tells
whether an exception is a stack fault and is only relevant when the
exception is IE (invalid operation.) The C1 bit determines whether a
stack fault is overflow or underflow and is only relevant when IS and IE
are set.
Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index a61f33d06ea3..cd2d5d5514fe 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -803,15 +803,17 @@ void math_error(void __user *eip) */ cwd = get_fpu_cwd(task); swd = get_fpu_swd(task); - switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) { + switch (swd & ~cwd & 0x3f) { case 0x000: default: break; case 0x001: /* Invalid Op */ - case 0x041: /* Stack Fault */ - case 0x241: /* Stack Fault | Direction */ + /* + * swd & 0x240 == 0x040: Stack Underflow + * swd & 0x240 == 0x240: Stack Overflow + * User must clear the SF bit (0x40) if set + */ info.si_code = FPE_FLTINV; - /* Should we clear the SF or let user space do it ???? */ break; case 0x002: /* Denormalize */ case 0x010: /* Underflow */ |