[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200227132256.987937595@linuxfoundation.org>
Date: Thu, 27 Feb 2020 14:33:47 +0100
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org, Will Deacon <will@...nel.org>,
Mark Rutland <mark.rutland@....com>,
Ard Biesheuvel <ardb@...nel.org>,
Catalin Marinas <catalin.marinas@....com>,
Marc Zyngier <maz@...nel.org>,
Suzuki K Poulose <suzuki.poulose@....com>,
Sasha Levin <sashal@...nel.org>
Subject: [PATCH 4.14 013/237] arm64: nofpsimd: Handle TIF_FOREIGN_FPSTATE flag cleanly
From: Suzuki K Poulose <suzuki.poulose@....com>
commit 52f73c383b2418f2d31b798e765ae7d596c35021 upstream
We detect the absence of FP/SIMD after an incapable CPU is brought up,
and by then we have kernel threads running already with TIF_FOREIGN_FPSTATE set
which could be set for early userspace applications (e.g, modprobe triggered
from initramfs) and init. This could cause the applications to loop forever in
do_nofity_resume() as we never clear the TIF flag, once we now know that
we don't support FP.
Fix this by making sure that we clear the TIF_FOREIGN_FPSTATE flag
for tasks which may have them set, as we would have done in the normal
case, but avoiding touching the hardware state (since we don't support any).
Cc: stable@...r.kernel.org # v4.14
Cc: Will Deacon <will@...nel.org>
Cc: Mark Rutland <mark.rutland@....com>
Reviewed-by: Ard Biesheuvel <ardb@...nel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@....com>
Acked-by: Marc Zyngier <maz@...nel.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@....com>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---
arch/arm64/kernel/fpsimd.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index f4fdf6420ac5c..4cd962f6c4302 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -206,8 +206,19 @@ void fpsimd_preserve_current_state(void)
*/
void fpsimd_restore_current_state(void)
{
- if (!system_supports_fpsimd())
+ /*
+ * For the tasks that were created before we detected the absence of
+ * FP/SIMD, the TIF_FOREIGN_FPSTATE could be set via fpsimd_thread_switch(),
+ * e.g, init. This could be then inherited by the children processes.
+ * If we later detect that the system doesn't support FP/SIMD,
+ * we must clear the flag for all the tasks to indicate that the
+ * FPSTATE is clean (as we can't have one) to avoid looping for ever in
+ * do_notify_resume().
+ */
+ if (!system_supports_fpsimd()) {
+ clear_thread_flag(TIF_FOREIGN_FPSTATE);
return;
+ }
local_bh_disable();
@@ -229,7 +240,7 @@ void fpsimd_restore_current_state(void)
*/
void fpsimd_update_current_state(struct fpsimd_state *state)
{
- if (!system_supports_fpsimd())
+ if (WARN_ON(!system_supports_fpsimd()))
return;
local_bh_disable();
--
2.20.1
Powered by blists - more mailing lists