On Tue, Aug 4, 2026 at 1:40 AM Matt Turner <[email protected]> wrote: > > ieee_swcr_to_fpcr() converts the software IEEE trap-enable and status > bits kept in thread_info.ieee_state into the hardware FPCR format. It > contained: > > fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41; > > FPCR_DNOD (bit 47) disables denormal operand traps: with it set the > hardware handles a denormal operand itself, treating it as zero, instead > of trapping for software completion. The intent was to set DNOD when the > user has not asked for SIGFPE on denormal operands, but > IEEE_TRAP_ENABLE_DNO is clear by default, so ieee_swcr_to_fpcr(0) always > set DNOD. > > Instructions built with the software completion suffix therefore never > trapped on a denormal operand. The hardware silently substituted zero > and produced wrong results, affecting every program compiled with -mieee > and default FPU settings, glibc included. > > Set FPCR_DNOD only when IEEE_MAP_DMZ is requested, which is exactly the > case where flushing denormal inputs to zero is what the user asked for. > DNOD then encodes MAP_DMZ, which ieee_fpcr_to_swcr() already recovers > from FPCR_DNZ, so drop its attempt to recover IEEE_TRAP_ENABLE_DNO from > DNOD; the DNO trap enable lives solely in ieee_state. > > Both functions are in a uapi header, so the encoding change is visible to > userspace, but nothing outside the kernel is known to depend on DNOD > carrying the DNO trap enable, and the kernel is the only writer of the > FPCR. > > This must not be backported on its own. Re-enabling denormal operand > traps exposes a second bug, fixed in the following patch: those traps > usually find an exact result, and for an exact result the emulator did > not write the FPCR back, leaving hardware-fabricated exception bits > visible to user space. Taken alone this change would make spurious > exception flags more common. > > The bug predates the git history, so there is no commit to reference in a > Fixes tag. > > Cc: [email protected] # 5.15+ > Signed-off-by: Matt Turner <[email protected]> > --- > arch/alpha/include/uapi/asm/fpu.h | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/arch/alpha/include/uapi/asm/fpu.h > b/arch/alpha/include/uapi/asm/fpu.h > index cea9eafa056f..d28dc36786e2 100644 > --- a/arch/alpha/include/uapi/asm/fpu.h > +++ b/arch/alpha/include/uapi/asm/fpu.h > @@ -101,7 +101,12 @@ ieee_swcr_to_fpcr(unsigned long sw) > | IEEE_TRAP_ENABLE_OVF)) << 48; > fp |= (~sw & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE)) << 57; > fp |= (sw & IEEE_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); > - fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41; > + /* > + * Disable denormal operand traps only when denormal inputs are to be > + * flushed to zero. Otherwise they must keep trapping, so that /S > + * instructions reach the kernel emulation handler. > + */ > + fp |= (sw & IEEE_MAP_DMZ ? FPCR_DNOD : 0); > return fp; > } > > @@ -116,7 +121,6 @@ ieee_fpcr_to_swcr(unsigned long fp) > | IEEE_TRAP_ENABLE_OVF); > sw |= (~fp >> 57) & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE); > sw |= (fp >> 47) & IEEE_MAP_UMZ; > - sw |= (~fp >> 41) & IEEE_TRAP_ENABLE_DNO; > return sw; > } > > > -- > 2.54.0 > Hi,
The new mapping of FPCR_DNOD to IEEE_MAP_DMZ looks correct to me. I tested the complete series with CONFIG_MATHEMU=y on the same machine and using the same glibc build. The kernel boots normally, and the glibc math testsuite improves from 48 to 28 failing test programs, with no new failing tests. Reviewed-by: Magnus Lindholm [email protected] Tested-by: Magnus Lindholm [email protected]
