All of lore.kernel.org
 help / color / mirror / Atom feed
* [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly
@ 2020-02-14 15:19 Suzuki K Poulose
  2020-02-14 15:19 ` [stable 4.14 PATCH 2/3] arm64: ptrace: nofpsimd: Fail FP/SIMD regset operations Suzuki K Poulose
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Suzuki K Poulose @ 2020-02-14 15:19 UTC (permalink / raw)
  To: stable
  Cc: gregkh, ard.biesheuvel, catalin.marinas, mark.rutland, maz,
	Suzuki K Poulose, Will Deacon, Ard Biesheuvel

commit 7ef1ab8792c50797c6c5c7c5150a02460 upstream

We set the compat_elf_hwcap bits unconditionally on arm64 to
include the VFP and NEON support. However, the FP/SIMD unit
is optional on Arm v8 and thus could be missing. We already
handle this properly in the kernel, but still advertise to
the COMPAT applications that the VFP is available. Fix this
to make sure we only advertise when we really have them.

Cc: stable@vger.kernel.org # v4.14
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 52 +++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 09c6499bc500..016381236294 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -41,9 +41,7 @@ EXPORT_SYMBOL_GPL(elf_hwcap);
 #define COMPAT_ELF_HWCAP_DEFAULT	\
 				(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
 				 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
-				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
-				 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
-				 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\
+				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_IDIV|\
 				 COMPAT_HWCAP_LPAE)
 unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
 unsigned int compat_elf_hwcap2 __read_mostly;
@@ -1134,17 +1132,30 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	{},
 };
 
-#define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
-	{							\
-		.desc = #cap,					\
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
+
+#define HWCAP_CPUID_MATCH(reg, field, s, min_value)		\
 		.matches = has_cpuid_feature,			\
 		.sys_reg = reg,					\
 		.field_pos = field,				\
 		.sign = s,					\
 		.min_field_value = min_value,			\
+
+#define __HWCAP_CAP(name, cap_type, cap)			\
+		.desc = name,					\
+		.type = ARM64_CPUCAP_SYSTEM_FEATURE,		\
 		.hwcap_type = cap_type,				\
 		.hwcap = cap,					\
+
+#define HWCAP_CAP(reg, field, s, min_value, cap_type, cap)	\
+	{							\
+		__HWCAP_CAP(#cap, cap_type, cap)		\
+		HWCAP_CPUID_MATCH(reg, field, s, min_value)	\
+	}
+
+#define HWCAP_CAP_MATCH(match, cap_type, cap)			\
+	{							\
+		__HWCAP_CAP(#cap, cap_type, cap)		\
+		.matches = match,				\
 	}
 
 static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
@@ -1177,8 +1188,35 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
 	{},
 };
 
+#ifdef CONFIG_COMPAT
+static bool compat_has_neon(const struct arm64_cpu_capabilities *cap, int scope)
+{
+	/*
+	 * Check that all of MVFR1_EL1.{SIMDSP, SIMDInt, SIMDLS} are available,
+	 * in line with that of arm32 as in vfp_init(). We make sure that the
+	 * check is future proof, by making sure value is non-zero.
+	 */
+	u32 mvfr1;
+
+	WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
+	if (scope == SCOPE_SYSTEM)
+		mvfr1 = read_sanitised_ftr_reg(SYS_MVFR1_EL1);
+	else
+		mvfr1 = read_sysreg_s(SYS_MVFR1_EL1);
+
+	return cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDSP_SHIFT) &&
+		cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDINT_SHIFT) &&
+		cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDLS_SHIFT);
+}
+#endif
+
 static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
 #ifdef CONFIG_COMPAT
+	HWCAP_CAP_MATCH(compat_has_neon, CAP_COMPAT_HWCAP, COMPAT_HWCAP_NEON),
+	HWCAP_CAP(SYS_MVFR1_EL1, MVFR1_SIMDFMAC_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv4),
+	/* Arm v8 mandates MVFR0.FPDP == {0, 2}. So, piggy back on this for the presence of VFP support */
+	HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFP),
+	HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv3),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [stable 4.14 PATCH 2/3] arm64: ptrace: nofpsimd: Fail FP/SIMD regset operations
  2020-02-14 15:19 [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Suzuki K Poulose
@ 2020-02-14 15:19 ` Suzuki K Poulose
  2020-02-14 15:19 ` [stable 4.14 PATCH 3/3] arm64: nofpsimd: Handle TIF_FOREIGN_FPSTATE flag cleanly Suzuki K Poulose
  2020-02-15 20:23 ` [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Sasha Levin
  2 siblings, 0 replies; 4+ messages in thread
From: Suzuki K Poulose @ 2020-02-14 15:19 UTC (permalink / raw)
  To: stable
  Cc: gregkh, ard.biesheuvel, catalin.marinas, mark.rutland, maz,
	Suzuki K Poulose, Will Deacon, Ard Biesheuvel

commit c9d66999f064947e6b577ceacc1eb2fbca6a8d3c upstream

When fp/simd is not supported on the system, fail the operations
of FP/SIMD regsets.

Cc: stable@vger.kernel.org # v4.14
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/kernel/ptrace.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 242527f29c41..e230b4dff960 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -624,6 +624,13 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 	return 0;
 }
 
+static int fpr_active(struct task_struct *target, const struct user_regset *regset)
+{
+	if (!system_supports_fpsimd())
+		return -ENODEV;
+	return regset->n;
+}
+
 /*
  * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
  */
@@ -634,6 +641,9 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 	struct user_fpsimd_state *uregs;
 	uregs = &target->thread.fpsimd_state.user_fpsimd;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	if (target == current)
 		fpsimd_preserve_current_state();
 
@@ -648,6 +658,9 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 	struct user_fpsimd_state newstate =
 		target->thread.fpsimd_state.user_fpsimd;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
 	if (ret)
 		return ret;
@@ -740,6 +753,7 @@ static const struct user_regset aarch64_regsets[] = {
 		 */
 		.size = sizeof(u32),
 		.align = sizeof(u32),
+		.active = fpr_active,
 		.get = fpr_get,
 		.set = fpr_set
 	},
@@ -914,6 +928,9 @@ static int compat_vfp_get(struct task_struct *target,
 	compat_ulong_t fpscr;
 	int ret, vregs_end_pos;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	uregs = &target->thread.fpsimd_state.user_fpsimd;
 
 	if (target == current)
@@ -947,6 +964,9 @@ static int compat_vfp_set(struct task_struct *target,
 	compat_ulong_t fpscr;
 	int ret, vregs_end_pos;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	uregs = &target->thread.fpsimd_state.user_fpsimd;
 
 	vregs_end_pos = VFP_STATE_SIZE - sizeof(compat_ulong_t);
@@ -1004,6 +1024,7 @@ static const struct user_regset aarch32_regsets[] = {
 		.n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
 		.size = sizeof(compat_ulong_t),
 		.align = sizeof(compat_ulong_t),
+		.active = fpr_active,
 		.get = compat_vfp_get,
 		.set = compat_vfp_set
 	},
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [stable 4.14 PATCH 3/3] arm64: nofpsimd: Handle TIF_FOREIGN_FPSTATE flag cleanly
  2020-02-14 15:19 [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Suzuki K Poulose
  2020-02-14 15:19 ` [stable 4.14 PATCH 2/3] arm64: ptrace: nofpsimd: Fail FP/SIMD regset operations Suzuki K Poulose
@ 2020-02-14 15:19 ` Suzuki K Poulose
  2020-02-15 20:23 ` [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Sasha Levin
  2 siblings, 0 replies; 4+ messages in thread
From: Suzuki K Poulose @ 2020-02-14 15:19 UTC (permalink / raw)
  To: stable
  Cc: gregkh, ard.biesheuvel, catalin.marinas, mark.rutland, maz,
	Suzuki K Poulose, Will Deacon, Ard Biesheuvel

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@vger.kernel.org # v4.14
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 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 f4fdf6420ac5..4cd962f6c430 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.24.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly
  2020-02-14 15:19 [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Suzuki K Poulose
  2020-02-14 15:19 ` [stable 4.14 PATCH 2/3] arm64: ptrace: nofpsimd: Fail FP/SIMD regset operations Suzuki K Poulose
  2020-02-14 15:19 ` [stable 4.14 PATCH 3/3] arm64: nofpsimd: Handle TIF_FOREIGN_FPSTATE flag cleanly Suzuki K Poulose
@ 2020-02-15 20:23 ` Sasha Levin
  2 siblings, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2020-02-15 20:23 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: stable, gregkh, ard.biesheuvel, catalin.marinas, mark.rutland,
	maz, Will Deacon, Ard Biesheuvel

On Fri, Feb 14, 2020 at 03:19:35PM +0000, Suzuki K Poulose wrote:
>commit 7ef1ab8792c50797c6c5c7c5150a02460 upstream
>
>We set the compat_elf_hwcap bits unconditionally on arm64 to
>include the VFP and NEON support. However, the FP/SIMD unit
>is optional on Arm v8 and thus could be missing. We already
>handle this properly in the kernel, but still advertise to
>the COMPAT applications that the VFP is available. Fix this
>to make sure we only advertise when we really have them.
>
>Cc: stable@vger.kernel.org # v4.14
>Cc: Will Deacon <will@kernel.org>
>Cc: Mark Rutland <mark.rutland@arm.com>
>Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
>Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

Queued for 4.14, thank you.

-- 
Thanks,
Sasha

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-02-15 20:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-14 15:19 [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Suzuki K Poulose
2020-02-14 15:19 ` [stable 4.14 PATCH 2/3] arm64: ptrace: nofpsimd: Fail FP/SIMD regset operations Suzuki K Poulose
2020-02-14 15:19 ` [stable 4.14 PATCH 3/3] arm64: nofpsimd: Handle TIF_FOREIGN_FPSTATE flag cleanly Suzuki K Poulose
2020-02-15 20:23 ` [stable 4.14 PATCH 1/3] arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly Sasha Levin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.