From nobody Fri Oct 2 07:45:25 2026 Received: from mail-yx1-f46.google.com (mail-yx1-f46.google.com [74.125.224.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93B43395AE9 for ; Mon, 3 Aug 2026 23:40:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785800453; cv=none; b=VPWPUL3mdJ9dBoS0hWLacvY1vh3d6N6FzaCJxeOEKp+WWbQIwZ2Z/lPgxD8HadBxFG/DEzkNlvAO/J57MGQXt92klv6GJcLmOlnIRudLfM99jgmN4d0ODcQsjCe95ihTWgvVRXDjgyECHv9msP1YgC8sWXtKOAyNfmml7rNon3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785800453; c=relaxed/simple; bh=YZg1odxiWek0UxsP57a8f13DBqPUmymS1YIGamKZW+Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Sa3RMqxvc+GQgw/A83JNzTHnUsr7NzZ4xusXlhTDyM7xhy4y4Ad3CHEuAbaFgpZnBpSwrvKNJwff/MxZLnnQhuh/UvyrtacQOrqp6+opxJTPWK1mjzC0neXsSNnKqwdmU/OPWFOHveGlIAGcuxNAfsUUOL1nX5cI3rRMQCNGqmE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=B06zjzZI; arc=none smtp.client-ip=74.125.224.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="B06zjzZI" Received: by mail-yx1-f46.google.com with SMTP id 956f58d0204a3-667971437d6so5502859d50.2 for ; Mon, 03 Aug 2026 16:40:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785800449; x=1786405249; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=iXt2lHl6V6DYOxKrsChpRVwvJNwCDOvF3knLtupIoSg=; b=B06zjzZIb4DrxrL4KvqLlHDn9RGSsjwqhOhkwKhmOUr9TLQKClY+YqrK7vqY70jjEJ PwgsgeL7uh2DbOLRXvkOgG1AwXVmafNqOf7G1692yDq4+UHUuOeNnisRffLMVcmfE6QC LLGxOaqZUWJDebuW0nkJKWitu7udF1/8aPzTjtBPkCbymJ/Hxp1FEOumvUBBj/OE8dOT u/2iwVKLoECCOPnyy0E+vV8pKFBdbGJnhreHvqGYuX0BFucddECVDaCwsyw2z6oobVsu lNn/1muTrj3YbiRuvVBLIm9IkZIqAH+VHQ3PBfvD9oW7FU3LvpIBG4t0xbZl6UpNtexw CVBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785800449; x=1786405249; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=iXt2lHl6V6DYOxKrsChpRVwvJNwCDOvF3knLtupIoSg=; b=R7xHg/jodEMsVy1+SoeaGZDEfeAbZkv/itqkDSdgPcdFFAq1qTtmcEI4YJrRTlCXzq h409jIoRxWdBFcD1T6teor3G0SLmRcJr6OD9j+RCsFzlNqIayEumeWF+lWX/3cWbrdrs KyYQHh5rTLvuAV6Ws1+b458V7B/9ms+PXBEXCe3FFnsXChWD6hDBmbBezQE2aWB5wBfn FlBI8kLAL2xN87T4n02LDYgVx1aV6fm3g07e+ZdBXCr2IGL9SB/D2MrCrpFQhP3FLyVY cWtsfVmzDWjWHKtUTuspEmTCMv/DkWFTkUDoRCfAsMWawEhX86HUSEcbRgnqtBXQkck8 VqbA== X-Forwarded-Encrypted: i=1; AHgh+RqDuMgG1Zk+cVyy08CIpkQK3bNhSnDyk3XFABE1xNfeMjrGbFlDMuz1i5wDYENgHge+OtOpR+CiAQXxagQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxQuFNYcvdt9KMrZ3RAazXz2pj2ZgrjIIF27lD0yTOz+gkfDbYy u15AGymPuuRkWlwsNZKCgefr0UqzOsFUnhrXIYWWqYNGz10wRBz4TcDJ X-Gm-Gg: AR+sD127oWwP+1MWbnxM2bo2he9MYvahWXmFRWvsC3FQFIGuvVXkTh7TzEQC8WsZ2+M 9haKD0o5CV0knL8INNpoKOT6AinUkftF0ZNyMm/brcuNnmKCAo1S5DAJ8A2SltkoW+1qiEj2m2w mKW2wqkxeHAMdB0MiwO7vhTQUxAxQgAm4Bq4zIlWEPfP3r68eJ9JTyAVMtNoR58LzDAi2fV5svh tF2Mn61c7NrtJ6OopNEDi1UquNWBEiyrQimGvM1ncU9Gysun1IKs5hCVjYX+8hU6ZYxs+5BZSYE 6B725gcccvDr5q88CAduHV3zYnrUPdFZni38TzJ5MkrD+Id85pVjqDa21esHNX6+0sBcOTwY/Zu txn71xoG0b+hcal44euuXLiKrzjENtfb/jgDgx8OAXS4Q3oGlEQLlsNNdo+p3dgeS3kjsTS9zts pw3ZYX7PDDcoQt7g3YYiDdHHCzzZjVjUmurtLXlROtu8mLKwDGnuG3saXQs80xKHk5kNIAcjw= X-Received: by 2002:a05:690e:480a:b0:668:8f89:762 with SMTP id 956f58d0204a3-6694efd03bamr9722268d50.1.1785800449430; Mon, 03 Aug 2026 16:40:49 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-66948b98babsm6681712d50.0.2026.08.03.16.40.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 16:40:48 -0700 (PDT) From: Matt Turner Date: Mon, 03 Aug 2026 19:40:45 -0400 Subject: [PATCH 1/3] alpha: fix ieee_swcr_to_fpcr setting FPCR_DNOD unconditionally Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260803-alpha-fp-exceptions-v1-1-c99d75608e60@gmail.com> References: <20260803-alpha-fp-exceptions-v1-0-c99d75608e60@gmail.com> In-Reply-To: <20260803-alpha-fp-exceptions-v1-0-c99d75608e60@gmail.com> To: Richard Henderson , Matt Turner , Magnus Lindholm Cc: linux-alpha@vger.kernel.org, linux-kernel@vger.kernel.org, sparclinux@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-sh@vger.kernel.org, "David S. Miller" , Andreas Larsson , stable@vger.kernel.org X-Mailer: b4 0.14.3 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 |=3D (~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: stable@vger.kernel.org # 5.15+ Signed-off-by: Matt Turner Reviewed-by: Magnus Lindholm linmag7@gmail.com Tested-by: Magnus Lindholm linmag7@gmail.com --- 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/as= m/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 |=3D (~sw & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE)) << 57; fp |=3D (sw & IEEE_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); - fp |=3D (~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 |=3D (sw & IEEE_MAP_DMZ ? FPCR_DNOD : 0); return fp; } =20 @@ -116,7 +121,6 @@ ieee_fpcr_to_swcr(unsigned long fp) | IEEE_TRAP_ENABLE_OVF); sw |=3D (~fp >> 57) & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE); sw |=3D (fp >> 47) & IEEE_MAP_UMZ; - sw |=3D (~fp >> 41) & IEEE_TRAP_ENABLE_DNO; return sw; } =20 --=20 2.54.0 From nobody Fri Oct 2 07:45:25 2026 Received: from mail-yx1-f46.google.com (mail-yx1-f46.google.com [74.125.224.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29DDF397920 for ; Mon, 3 Aug 2026 23:40:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785800454; cv=none; b=rBKc5YRTK8V0+RTLk9hgT0Z7mMmxmFDNn1BPQXRvOWE4+BO4gTqo/IFpDDQbQvrS2lknA6i+xmotvnvsudk2W2QnWcvRVdfyuuY9VunyxjAfpxHXoLdHYyqI/hU1iZrE9GYlMSpBWIe5lVMmmWvKxclkKLB8priqlV3Wduvf58Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785800454; c=relaxed/simple; bh=l7nUfbmcaF4fNgdDGLaluLSkk7Vtw5eJN5GAj2QQfq8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=b5Y02rXHerX4WOi7XlNPHBAol/teNd1v9+IiMC+dIlrPGcw9Nhbxq86Tg9EeVbE6hOadU3qJvnsFbXxMaKpBv7irnOYBPH5GnRA6SP7LnR/qGiDT9W1vt7SdlObdNa6buOKlAwOXouSLvjNUbntCgFxxczPQb+ybYsOQ69TAhhw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UGgpVXP/; arc=none smtp.client-ip=74.125.224.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UGgpVXP/" Received: by mail-yx1-f46.google.com with SMTP id 956f58d0204a3-6679d88abdcso5648242d50.2 for ; Mon, 03 Aug 2026 16:40:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785800451; x=1786405251; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+2j9pfRfEIp9EnFpow/3t02qd283vXOlzX6oo/fcXlc=; b=UGgpVXP/khMSfc9ttEUIqTVy5cbTCBDtfR2MBMSdv6FTzuTDrWOSyTgB8TgqULTS5A VINTeLpRFN0f85mCyyiRlwMildC/IkPd+byPa0Z9UVsOx4yjtxxnWEWQpheimZIe5/lG pmxv3ALKrCSP2AcF4rIkKhBYBxrpKvwFJBjAKy9uKIxmR/aQAf8ddak57Q+cAbjE+PLb ytu9n2aZ6mqfLgtVV8IvFUwZ6SV4pRWNFarSLTIQUrkt57hHJa1Bfr6FVjpg0kB4FuJu 4u1va7P8H+4gl12h1sIxPWx4q6tKHz5IkINuC2Y6hLny7yM3aySom7ectyQJGfODyHI1 4mjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785800451; x=1786405251; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=+2j9pfRfEIp9EnFpow/3t02qd283vXOlzX6oo/fcXlc=; b=kUuPCB1z+cMJUlCuBzRw/XCcJJy3EiEF/ykj4T0pwTCWquyHKnW9JjI/uvMzP+mLT6 LS6v4wKM/lCH+uB6Trb/jepneRqhAXTH3jz7jnuf/+lbEriAp34kEaNCiByYDEbbpxGO 1hyuRFTX8rF7J/9SgY4nAHrtnM0eKHD23/uQ7VJN0jvUuOUdWVNe8AadEk523tXLUf2V FQSnZJUzT44uf1j86V6oM8c/b/xMYgqA3okfc7buaR71OmX/p1Cxh3h8gVwnsXW2kxmb IWx9PwGCWFg6qJZ4lEs9mRXT0MssJYVlMuyxhHFJnYLCR2t7V8uX6d8nB+hNrd/RDkmw VPIw== X-Forwarded-Encrypted: i=1; AHgh+RrrYdvgratGaUUbkydzMC4yKkMyYxQkdc028muZ4iltPQU0Ifj/1UFzvgHhAHi5k4WMToly/JcNT7+DjpA=@vger.kernel.org X-Gm-Message-State: AOJu0Yxz8IJIz/Mkxjv0n3z/yfm+WrlIn2iXL0vlDAyf4a2Ao2j6lCAV jUoQPKZtOb2XI8J7HR0F6NJ/Nec5I3fU1pC+M1W7mpjhHPa7A385a9c4 X-Gm-Gg: AR+sD11YfVnyQ3N5sd7kfsQSZgfbrCUlxU0LFjhC2wEnn3Rvy67GREQLviJUOdGUuvU IJM4HDYic2gpveAN6DRnnNr1FlrMgn8nE9yq11CJjYvdOgb0CB9dqvtEFiTB2+NDte5ryPT48yW Q9FA36vEEr390PFAmnSZ8J5rCjUKUwJLDEpjDVYWi9WjrmGyLk+1rCVW4fJlGQNxmRgacHUoh18 6llA5FRz1dr/AtUcrqOtnxt/H8vNy74PITJxlnS27jxiAHHVImzsTGFzwDMLkRuewPC/LZWXlyM ImmtbgEmmp/vb1MymCJ9CP9ATMK0q0noqOWiulldgPmsdVEy1XvsjpzL2Mecesv2S6bShZNWeJv iwLY+xfzZ4jLZpAbe/aRozBsyLrMGzJ2pIF7PmK4/+3Gl5EXF5QuoARyjjLdycU1du+jJfYzrZH btW7JHjzTMVLF5xJXtZN/7i68XtaDx8bI3kGsahVHOzc686CyC3hoPvHFR1itm X-Received: by 2002:a05:690c:e3d1:b0:81e:f1e3:52ad with SMTP id 00721157ae682-81fd4ba85a4mr156253787b3.30.1785800450957; Mon, 03 Aug 2026 16:40:50 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 00721157ae682-81fccf2e2b0sm62638757b3.8.2026.08.03.16.40.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 16:40:50 -0700 (PDT) From: Matt Turner Date: Mon, 03 Aug 2026 19:40:46 -0400 Subject: [PATCH 2/3] alpha: don't leak hardware-fabricated FP exception bits to user space Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260803-alpha-fp-exceptions-v1-2-c99d75608e60@gmail.com> References: <20260803-alpha-fp-exceptions-v1-0-c99d75608e60@gmail.com> In-Reply-To: <20260803-alpha-fp-exceptions-v1-0-c99d75608e60@gmail.com> To: Richard Henderson , Matt Turner , Magnus Lindholm Cc: linux-alpha@vger.kernel.org, linux-kernel@vger.kernel.org, sparclinux@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-sh@vger.kernel.org, "David S. Miller" , Andreas Larsson , stable@vger.kernel.org X-Mailer: b4 0.14.3 On EV6 and later the hardware records exception status bits in the FPCR before delivering a software completion trap, and those bits can be wrong for the instruction that trapped. Converting a double that is exactly representable as a subnormal float sets FPCR_UNF even though the result is exact, and an underflow trap additionally sets FPCR_INE even when the emulated operation turns out to be exact. alpha_fp_emul() only wrote the FPCR when soft-fp raised an exception, so whenever it determined that the instruction was exact the fabricated bits stayed in the FPCR and were reported to user space by fetestexcept(). Pass the exception summary register down from do_entArith() so the handler can tell which exceptions the hardware attributed to the trapping instruction, and always write the FPCR. Clear the exceptions that the trap reported but that soft-fp did not raise. EXC_SUM reports only the underflow or overflow when the hardware also set INE, so treat INE as a candidate in that case, and treat a trap with no reported exception as a denormal operand trap, for which the hardware can fabricate INE and UNF as well. Bits that software has already confirmed in ieee_state belong to this or an earlier instruction and are never cleared. The imprecise path passes no summary. There the trap was taken somewhere in the trap shadow, so EXC_SUM is not attribution for the instruction being re-executed -- and only EV6, which traps precisely and so never takes that path, has fabricated bits to clear. For the same reason the clearing is guarded by implver(), matching swcr_update_status(). On an UP1500 (EV68) this takes the glibc math testsuite from 831 failures to 28, the remainder being unrelated to exception status. This belongs with the preceding fix to ieee_swcr_to_fpcr(), and should not be backported without it -- nor it without this. That fix stops FPCR_DNOD being set unconditionally, so denormal operand traps start firing again. Those traps very often find an exact result, which is precisely the case where the old code left the FPCR unwritten and the fabricated bits visible. Applied alone it would make spurious exception flags more common, not less. One case cannot be resolved here: an inexact instruction without the software completion suffix never traps, so its INE reaches the FPCR without being recorded anywhere else. Such a bit is indistinguishable from an INE the hardware fabricated for a trapping instruction, and is lost if an underflow or overflow trap with an exact result follows it. The FPCR is the only record of those instructions and it carries no attribution. The bug predates the git history, so there is no commit to reference in a Fixes tag. Cc: stable@vger.kernel.org # 5.15+ Signed-off-by: Matt Turner Reviewed-by: Magnus Lindholm linmag7@gmail.com Tested-by: Magnus Lindholm linmag7@gmail.com --- arch/alpha/kernel/traps.c | 6 ++-- arch/alpha/math-emu/math.c | 88 ++++++++++++++++++++++++++++++++++++++++--= ---- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 7004397937cf..7cd20e5f9ee0 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -166,12 +166,12 @@ static long dummy_emul(void) { return 0; } long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writem= ask) =3D (void *)dummy_emul; EXPORT_SYMBOL_GPL(alpha_fp_emul_imprecise); -long (*alpha_fp_emul) (unsigned long pc) +long (*alpha_fp_emul) (unsigned long pc, unsigned long summary) =3D (void *)dummy_emul; EXPORT_SYMBOL_GPL(alpha_fp_emul); #else long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask= ); -long alpha_fp_emul (unsigned long pc); +long alpha_fp_emul (unsigned long pc, unsigned long summary); #endif =20 asmlinkage void @@ -185,7 +185,7 @@ do_entArith(unsigned long summary, unsigned long write_= mask, emulate the instruction. If the processor supports precise exceptions, we don't have to search. */ if (!amask(AMASK_PRECISE_TRAP)) - si_code =3D alpha_fp_emul(regs->pc - 4); + si_code =3D alpha_fp_emul(regs->pc - 4, summary); else si_code =3D alpha_fp_emul_imprecise(regs, write_mask); if (si_code =3D=3D 0) diff --git a/arch/alpha/math-emu/math.c b/arch/alpha/math-emu/math.c index 68d420bfd3c0..e3f2df3729e3 100644 --- a/arch/alpha/math-emu/math.c +++ b/arch/alpha/math-emu/math.c @@ -52,13 +52,13 @@ MODULE_DESCRIPTION("FP Software completion module"); MODULE_LICENSE("GPL v2"); =20 extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long); -extern long (*alpha_fp_emul) (unsigned long pc); +extern long (*alpha_fp_emul) (unsigned long pc, unsigned long summary); =20 static long (*save_emul_imprecise)(struct pt_regs *, unsigned long); -static long (*save_emul) (unsigned long pc); +static long (*save_emul) (unsigned long pc, unsigned long summary); =20 long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long); -long do_alpha_fp_emul(unsigned long); +long do_alpha_fp_emul(unsigned long, unsigned long); =20 static int alpha_fp_emul_init_module(void) { @@ -86,7 +86,22 @@ module_exit(alpha_fp_emul_cleanup_module); =20 =20 /* - * Emulate the floating point instruction at address PC. Returns -1 if the + * Exception bits of the exception summary register (EXC_SUM). Bit 0 is t= he + * software completion bit; bits 1 through 5 report the exceptions the + * hardware attributed to the trapping instruction, and lie at the same + * positions as the corresponding IEEE_TRAP_ENABLE_* bits. + */ +#define EXC_SUM_INV (1UL << 1) +#define EXC_SUM_DZE (1UL << 2) +#define EXC_SUM_OVF (1UL << 3) +#define EXC_SUM_UNF (1UL << 4) +#define EXC_SUM_INE (1UL << 5) +#define EXC_SUM_MASK (EXC_SUM_INV | EXC_SUM_DZE | EXC_SUM_OVF \ + | EXC_SUM_UNF | EXC_SUM_INE) + +/* + * Emulate the floating point instruction at address PC. SUMMARY is the + * exception summary register the trap was delivered with. Returns -1 if = the * instruction to be emulated is illegal (such as with the opDEC trap), el= se * the SI_CODE for a SIGFPE signal, else 0 if everything's ok. * @@ -95,7 +110,7 @@ module_exit(alpha_fp_emul_cleanup_module); * stick the result of the operation into the appropriate register. */ long -alpha_fp_emul (unsigned long pc) +alpha_fp_emul (unsigned long pc, unsigned long summary) { FP_DECL_EX; FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); @@ -300,12 +315,56 @@ alpha_fp_emul (unsigned long pc) swcr |=3D (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); current_thread_info()->ieee_state |=3D (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + } =20 - /* Update hardware control register. */ - fpcr &=3D (~FPCR_MASK | FPCR_DYN_MASK); - fpcr |=3D ieee_swcr_to_fpcr(swcr); - wrfpcr(fpcr); + /* + * EV6 records exception status bits in the FPCR before delivering the + * software completion trap, and swcr_update_status() above merged them + * into SWCR. Some can be wrong for the instruction we just emulated: + * a CVTTS of a value exactly representable as a subnormal sets FPCR_UNF + * even though the result is exact. Clear the exceptions the trap + * reported but that soft-fp did not raise. + */ + if (implver() =3D=3D IMPLVER_EV6) { + unsigned long spurious =3D summary & EXC_SUM_MASK; =20 + if (spurious & (EXC_SUM_UNF | EXC_SUM_OVF)) { + /* + * EXC_SUM reports only the underflow or overflow, + * but the hardware sets INE alongside it in the FPCR. + */ + spurious |=3D EXC_SUM_INE; + } else if (!spurious) { + /* + * No exception reported, so this was a denormal + * operand trap, for which INE and UNF can be + * fabricated as well. + */ + spurious =3D EXC_SUM_INE | EXC_SUM_UNF; + } + + /* + * Never clear an exception software has confirmed. Every + * instruction that genuinely raises one traps for software + * completion and is recorded in ieee_state above, so a bit + * found there -- including one just set from _fex -- belongs + * to this or an earlier instruction and must survive. + */ + spurious &=3D ~(current_thread_info()->ieee_state + >> IEEE_STATUS_TO_EXCSUM_SHIFT); + + swcr &=3D ~(spurious << IEEE_STATUS_TO_EXCSUM_SHIFT); + } + + /* + * Update hardware control register. This has to happen even when + * soft-fp raised nothing, to clear any fabricated bits. + */ + fpcr &=3D (~FPCR_MASK | FPCR_DYN_MASK); + fpcr |=3D ieee_swcr_to_fpcr(swcr); + wrfpcr(fpcr); + + if (_fex) { /* Do we generate a signal? */ _fex =3D _fex & swcr & IEEE_TRAP_ENABLE_MASK; si_code =3D 0; @@ -387,9 +446,16 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigne= d long write_mask) break; } if (!write_mask) { - /* Re-execute insns in the trap-shadow. */ + /* + * Re-execute insns in the trap-shadow. Pass no + * exception summary: it describes the trap, which + * was taken anywhere in the shadow, and so is not + * attribution for this instruction. Nothing is + * lost, since only EV6 -- which traps precisely and + * never comes this way -- needs it. + */ regs->pc =3D trigger_pc + 4; - si_code =3D alpha_fp_emul(trigger_pc); + si_code =3D alpha_fp_emul(trigger_pc, 0); goto egress; } trigger_pc -=3D 4; --=20 2.54.0 From nobody Fri Oct 2 07:45:25 2026 Received: from mail-yw1-f171.google.com (mail-yw1-f171.google.com [209.85.128.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7450A395AF8 for ; Mon, 3 Aug 2026 23:40:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785800455; cv=none; b=H7GCGQBvX92kTfKXzRKapEYy9mRHhgn1WE1c3G4luDtWWRR5tIvQmA9bjdPDKAbVGXNhmomf8My0A7qBXpUsYIVi+bP+Dyf9OfNYkBe0ksutdhuKYcktw5R/uIzaPrnAVIg5KyGzo5GVlJ92nbsjqgZjVK1RKb7O6WOw3c8ThHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785800455; c=relaxed/simple; bh=wvu0uj6TEyjFZkFm/MbHPEdtVkNq6aaBrvr0yXB4eJ0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=G7qRy4G/VVPrNUM3PsDBLjhdTLVDllzW9hxhN0ps/hLLMsfw+w1YCFr0FDT7gLbIjfmHVCS/Ddjhf1GMCRIJtf0Juht/uYPcnxMtYI/DByPHiyFvxzYR6LtePhXnQGEDZaaT5XXzQfc9C+I1zrH6Qkc9eG/0RCsg1Pd/1DhAyd4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=c85sAWlT; arc=none smtp.client-ip=209.85.128.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="c85sAWlT" Received: by mail-yw1-f171.google.com with SMTP id 00721157ae682-81e8fa1b8d6so51756127b3.1 for ; Mon, 03 Aug 2026 16:40:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785800452; x=1786405252; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5Jv9folb9jOklDdXuGWBrNQv0WmbSuUwS788YmUFoOM=; b=c85sAWlTEkWzRa9zoVMY3/0oeKRUVNF78t9ZDw36JqbdBa7+ObsHpT6hZ1BFV2o5VZ uZe8hqrE/rwIL8+gWt0308XOasXDtW75MG09m/6537WUZzYGt8Wl7l4ElYM/yTPuYhhA ECs5jND4NFMV0bN66wB1jsls/Z0JOHPFmMzroKHypMUPg6VXMjvkJ5EvBS+BXU1m7YT/ RsxT8UpJfjuDmMo0v6C+yP2HLtwJw9r8BbtzxqMl1nDAZ1hnlDAF+tkAr0N9JOooDu3L aq5r/hG3WcqOsW28Z674iOQpcd7s0aEbACI3UgymtmQc5GJNTO8xDCSMQbKr3xmKOcuZ A1XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785800452; x=1786405252; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=5Jv9folb9jOklDdXuGWBrNQv0WmbSuUwS788YmUFoOM=; b=AIAijWJrCDDzYEdqnMPlqrhQImeDvdFOVbzkGHC3EUboxCW4VKCe7zyeDukfmiXoXv T+3AfvV+V6gd0AtXc+qa90QddUOD4vQ7T0mRJsHUuOfn9LG+ZUaDMfTXjwgNZpayKyO1 QCSyaxc9sYc6GmCdSSpxBNZWIf/x+13OrOhy7WhgftYcbdBAZ6nxzHFgfiIAsk5VQYBx CK3JWdKQitJ4L58sBcnPSmkU7yWS9xz4jnZGxzucBaFez9u5yNiXgT7C9ZiJs4rSSXi3 fyIVnjiyijZ1s6BwD/HFSQqUDadp30wJh2HBVj6YCP5KYWNEHGAFwQcqPF2iSMQfb+Eu D7pg== X-Forwarded-Encrypted: i=1; AHgh+RrnMPubiJpfk303Xqr164epmicZRnR6a0l/7eu5rYQwhiqh49KdBRsr8nZf8ZwjIdaI4ZHEnF9Ne7QUw1A=@vger.kernel.org X-Gm-Message-State: AOJu0YxBMEPlpEDwSPkdRmaPesv3zJ1NVTAucvR6NVPwRNkNY375kKo4 ePZvMfBqx+SO3y/04PNRS1qFmeqsC7WPx6OxIeLS/4qAMR0SF88VDh+F X-Gm-Gg: AR+sD10hdISRGCPHwOMnvsoPsfHXLxal4U8idCOFjFem0Gv/r551gLVQvvKACaQwkaG 2pQivrk4CQ179HMY6F00NINVQp35kRzBkCHEdo+1kdYhzEu4Etmzt/TlIfBvkkV4zwv20fXwF1G f2qj4tEfmy3cAjyDAKklvD8kcyVdmqrZ4oTxuapEZpPJiGMsUEkhaZIcvT6NoyKlLRzIismkBXd KGm5TJ3ZaBrIyj4aWHFaDohSG+saQGErSc2QG7r8rpS3xc6ZHDftdsXJxpc2HUwDjqRiR0OO/6b WyVboCYhbkz3FK+owuSUkcB3VKxzv2P31O1onMuqXaHF3z4ujbwil01Y0uVE7CfTDGDz3feDbwy jB4BVluXVRAPfcX/ZUXhIMfV9Bjr1jYoMmdTxWUcj+kTSOq8C51MFa38uQcjTAUfz58HhrZbwi4 bkyV0Bg6X6dOZ9xoULqD2BRRmk7WlAoXVxYmVlWMIKBkgd0PLJk94oshBd9YqEodt1zRFe1Do= X-Received: by 2002:a05:690c:ecf:b0:814:7a54:3a93 with SMTP id 00721157ae682-81fd4b372d9mr163845447b3.23.1785800452413; Mon, 03 Aug 2026 16:40:52 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 00721157ae682-81fcd0d68b0sm65571757b3.28.2026.08.03.16.40.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 16:40:51 -0700 (PDT) From: Matt Turner Date: Mon, 03 Aug 2026 19:40:47 -0400 Subject: [PATCH 3/3] alpha: determine tininess after rounding in the FP emulation Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260803-alpha-fp-exceptions-v1-3-c99d75608e60@gmail.com> References: <20260803-alpha-fp-exceptions-v1-0-c99d75608e60@gmail.com> In-Reply-To: <20260803-alpha-fp-exceptions-v1-0-c99d75608e60@gmail.com> To: Richard Henderson , Matt Turner , Magnus Lindholm Cc: linux-alpha@vger.kernel.org, linux-kernel@vger.kernel.org, sparclinux@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-sh@vger.kernel.org, "David S. Miller" , Andreas Larsson , stable@vger.kernel.org X-Mailer: b4 0.14.3 IEEE 754 lets an architecture determine tininess of a floating-point result either before or after rounding, but requires the same choice for every operation. Alpha determines it after rounding, and stdlib's tst-tininess confirms the hardware does so for the results it produces itself. The soft-fp emulation has no notion of the distinction and always determines tininess before rounding, so a result that the hardware would not consider tiny is reported as underflowing whenever the instruction happens to trap for software completion. The two paths then disagree on the same machine. A multiply of the largest subnormal double by 1 + 2^-52 rounds up to the smallest normal and raises no underflow when the operands are normal, but raises it when an operand is subnormal and the instruction traps: glibc math testsuite, test-float32x-float64-mul: Failure: mul_double (0x3.ffffffffffffcp-1024, 0x1.0000000000001p+0): Exception "Underflow" set Add _FP_TININESS_AFTER_ROUNDING, as glibc's copy of soft-fp has, and set it for alpha. It determines tininess by rounding a copy of the result as if the exponent range were unbounded, which is what the definition asks for; a plain check of whether the rounded result came out normal is not equivalent and would be wrong for values that stay tiny under an unbounded exponent range but round up to the smallest normal in the subnormal grid. The macro defaults to zero, so powerpc, sh and sparc keep determining tininess before rounding as they do now. Cc: stable@vger.kernel.org # 5.15+ Signed-off-by: Matt Turner Reviewed-by: Magnus Lindholm linmag7@gmail.com Tested-by posted). Tested-by: Magnus Lindholm linmag7@gmail.com --- arch/alpha/include/asm/sfp-machine.h | 4 ++++ include/math-emu/op-common.h | 23 +++++++++++++++++++++-- include/math-emu/soft-fp.h | 8 ++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/sfp-machine.h b/arch/alpha/include/asm/= sfp-machine.h index 5fe63afbd474..bff1ad963c68 100644 --- a/arch/alpha/include/asm/sfp-machine.h +++ b/arch/alpha/include/asm/sfp-machine.h @@ -59,6 +59,10 @@ R##_c =3D FP_CLS_NAN; \ } while (0) =20 +/* Alpha determines tininess after rounding, so the emulation must do the + same as the hardware does for the results it produces itself. */ +#define _FP_TININESS_AFTER_ROUNDING 1 + /* Obtain the current rounding mode. */ #define FP_ROUNDMODE mode #define FP_RND_NEAREST (FPCR_DYN_NORMAL >> FPCR_DYN_SHIFT) diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index 8ce066c035cf..1d1ce5c08efc 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -135,6 +135,24 @@ do { \ else \ { \ /* we've got a denormalized number */ \ + int _FP_PACK_CANONICAL_is_tiny =3D 1; \ + if (_FP_TININESS_AFTER_ROUNDING && X##_e =3D=3D 0) \ + { \ + /* Architectures that detect tininess after rounding \ + only signal underflow if the result is still \ + subnormal once rounded as if the exponent range \ + were unbounded. Round a copy to find out. */ \ + FP_DECL_##fs(_FP_PACK_CANONICAL_T); \ + /* The class field is not used by the rounding below, \ + and is unused entirely where this block is dead. */ \ + (void)_FP_PACK_CANONICAL_T##_c; \ + _FP_FRAC_COPY_##wc(_FP_PACK_CANONICAL_T, X); \ + _FP_PACK_CANONICAL_T##_s =3D X##_s; \ + _FP_PACK_CANONICAL_T##_e =3D X##_e; \ + _FP_ROUND(wc, _FP_PACK_CANONICAL_T); \ + if (_FP_FRAC_OVERP_##wc(fs, _FP_PACK_CANONICAL_T)) \ + _FP_PACK_CANONICAL_is_tiny =3D 0; \ + } \ X##_e =3D -X##_e + 1; \ if (X##_e <=3D _FP_WFRACBITS_##fs) \ { \ @@ -161,8 +179,9 @@ do { \ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ } \ } \ - if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ - (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ + if (_FP_PACK_CANONICAL_is_tiny \ + && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ + (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))) \ FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ } \ else \ diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h index 5650c1628383..02ada0a9fca1 100644 --- a/include/math-emu/soft-fp.h +++ b/include/math-emu/soft-fp.h @@ -31,6 +31,14 @@ #include #endif =20 +/* Whether the architecture determines tininess of a floating-point + result after rounding rather than before it. IEEE 754 permits either + but requires the same choice for every operation, so this has to agree + with what the hardware does for the results it produces itself. */ +#ifndef _FP_TININESS_AFTER_ROUNDING +#define _FP_TININESS_AFTER_ROUNDING 0 +#endif + #define _FP_WORKBITS 3 #define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) #define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) --=20 2.54.0