aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch')
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch98
1 files changed, 98 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch b/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch
new file mode 100644
index 0000000000..221b2774a1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch
@@ -0,0 +1,98 @@
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 1 Jul 2009 21:20:59 +0000 (+0300)
+Subject: So far vfp_sync_state worked only for threads other than the current one. This worked...
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=23671113997664ae55c8132fc4a56e676d5b46c7
+
+So far vfp_sync_state worked only for threads other than the current one. This worked for tracing other threads, but not for PTRACE_TRACEME. Syncing for the current thread will also be needed by an upcoming patch adding support for VFP context save / restore around signal handlers.
+
+For SMP we need get_cpu now, since we have to protect the FPEXC
+register, other than this things remained the same for threads other
+than the current.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 01599c4..969b77a 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -380,12 +380,19 @@ static inline void vfp_pm_init(void) { }
+ #endif /* CONFIG_PM */
+
+ /*
+- * Synchronise the hardware VFP state of a thread other than current with the
+- * saved one. This function is used by the ptrace mechanism.
++ * Synchronise the hardware VFP state of a thread with the saved one.
++ * This function is used by the ptrace mechanism and the signal handler path.
+ */
+-#ifdef CONFIG_SMP
+ void vfp_sync_state(struct thread_info *thread)
+ {
++ unsigned int cpu = get_cpu();
++ u32 fpexc = fmrx(FPEXC);
++ int vfp_enabled;
++ int self;
++
++ vfp_enabled = fpexc & FPEXC_EN;
++ self = thread == current_thread_info();
++#ifdef CONFIG_SMP
+ /*
+ * On SMP systems, the VFP state is automatically saved at every
+ * context switch. We mark the thread VFP state as belonging to a
+@@ -393,18 +400,22 @@ void vfp_sync_state(struct thread_info *thread)
+ * needed.
+ */
+ thread->vfpstate.hard.cpu = NR_CPUS;
+-}
+-#else
+-void vfp_sync_state(struct thread_info *thread)
+-{
+- unsigned int cpu = get_cpu();
+- u32 fpexc = fmrx(FPEXC);
+-
+ /*
+- * If VFP is enabled, the previous state was already saved and
+- * last_VFP_context updated.
++ * Only the current thread's saved VFP context can be out-of-date.
++ * For others there is nothing else to do, since we already ensured
++ * force loading above.
+ */
+- if (fpexc & FPEXC_EN)
++ if (!self)
++ goto out;
++#endif
++ /*
++ * If the VFP is enabled only the current thread's saved VFP
++ * context can get out-of-date. For other threads the context
++ * was updated when the current thread started to use the VFP.
++ * This also means that the context will be reloaded next time
++ * the thread uses the VFP, so no need to enforce it.
++ */
++ if (vfp_enabled && !self)
+ goto out;
+
+ if (!last_VFP_context[cpu])
+@@ -413,8 +424,14 @@ void vfp_sync_state(struct thread_info *thread)
+ /*
+ * Save the last VFP state on this CPU.
+ */
+- fmxr(FPEXC, fpexc | FPEXC_EN);
++ if (!vfp_enabled)
++ fmxr(FPEXC, fpexc | FPEXC_EN);
+ vfp_save_state(last_VFP_context[cpu], fpexc);
++ /*
++ * Disable VFP in case it was enabled so that the force reload
++ * can happen.
++ */
++ fpexc &= ~FPEXC_EN;
+ fmxr(FPEXC, fpexc);
+
+ /*
+@@ -426,7 +443,6 @@ void vfp_sync_state(struct thread_info *thread)
+ out:
+ put_cpu();
+ }
+-#endif
+
+ #include <linux/smp.h>
+