aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-05-15 15:51:54 +0100
committerChristian Neumüller <cn00@gmx.at>2014-12-30 12:53:31 +0100
commitb49f57f5db5d65e3d7e3b097f0c3138730c19356 (patch)
treef01acef88840769e11d33e6efbc099bdce0cc1af
parentef1bd2814672fe472f8cb21b43371445f8c24ec3 (diff)
downloadkernel_samsung_smdk4412-b49f57f5db5d65e3d7e3b097f0c3138730c19356.zip
kernel_samsung_smdk4412-b49f57f5db5d65e3d7e3b097f0c3138730c19356.tar.gz
kernel_samsung_smdk4412-b49f57f5db5d65e3d7e3b097f0c3138730c19356.tar.bz2
ARM: 7419/1: vfp: fix VFP flushing regression on sigreturn path
Commit ff9a184c ("ARM: 7400/1: vfp: clear fpscr length and stride bits on entry to sig handler") flushes the VFP state prior to entering a signal handler so that a VFP operation inside the handler will trap and force a restore of ABI-compliant registers. Reflushing and disabling VFP on the sigreturn path is predicated on the saved thread state indicating that VFP was used by the handler -- however for SMP platforms this is only set on context-switch, making the check unreliable and causing VFP register corruption in userspace since the register values are not necessarily those restored from the sigframe. This patch unconditionally flushes the VFP state after a signal handler. Since we already perform the flush before the handler and the flushing itself happens lazily, the redundant flush when VFP is not used by the handler is essentially a nop. Change-Id: Ia9ec6384fae3281def1dc93914af336857a09949 Reported-by: Jon Medhurst <tixy@linaro.org> Signed-off-by: Jon Medhurst <tixy@linaro.org> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Lanchon <lanchon@gmail.com>
-rw-r--r--arch/arm/vfp/vfpmodule.c14
1 files changed, 2 insertions, 12 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index cd45626..6c80b61 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -581,12 +581,6 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
* entry.
*/
hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK);
-
- /*
- * Disable VFP in the hwstate so that we can detect if it gets
- * used.
- */
- hwstate->fpexc &= ~FPEXC_EN;
return 0;
}
@@ -599,12 +593,8 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp,
unsigned long fpexc;
int err = 0;
- /*
- * If VFP has been used, then disable it to avoid corrupting
- * the new thread state.
- */
- if (hwstate->fpexc & FPEXC_EN)
- vfp_flush_hwstate(thread);
+ /* Disable VFP to avoid corrupting the new thread state. */
+ vfp_flush_hwstate(thread);
/*
* Copy the floating point registers. There can be unused