[RFC PATCH v2 1/2] ARM: VFP: add support to sync the VFP state of the current thread

Russell King - ARM Linux linux at arm.linux.org.uk
Sat Feb 6 06:20:48 EST 2010


On Sat, Feb 06, 2010 at 10:32:30AM +0000, Russell King - ARM Linux wrote:
> On Thu, Feb 04, 2010 at 11:38:02PM +0200, Imre Deak wrote:
> > 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.
> 
> I don't think we should make this function any more complicated than it
> already is.

... and the more I look at vfp_sync_state(), the more I believe it's
trying to do its job in a really obscure way.

Essentially, last_VFP_context[] tracks who owns the state in the VFP
hardware.  If last_VFP_context[] is the context for the thread which
we're interested in, then the VFP hardware has context which is not
saved in the software state - so we need to bring the software state
up to date.

If last_VFP_context[] is for some other thread, we really don't care
what state the VFP hardware is in; it doesn't contain any information
pertinent to the thread we're trying to deal with - so leave the
hardware well alone.

As a side effect, this makes vfp_sync_state() callable for the current
thread, and allows it to do the right thing there as well.

diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f60a540..6447d78 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -444,32 +444,28 @@ void vfp_sync_state(struct thread_info *thread)
 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.
+	 * If the thread we're interested in is the current owner of the
+	 * hardware VFP state, then we need to save its state.
 	 */
-	if (fpexc & FPEXC_EN)
-		goto out;
-
-	if (!last_VFP_context[cpu])
-		goto out;
+	if (last_VFP_context[cpu] == &thread->vfpstate) {
+		u32 fpexc = fmrx(FPEXC);
 
-	/*
-	 * Save the last VFP state on this CPU.
-	 */
-	fmxr(FPEXC, fpexc | FPEXC_EN);
-	vfp_save_state(last_VFP_context[cpu], fpexc);
-	fmxr(FPEXC, fpexc);
+		/*
+		 * Save the last VFP state on this CPU.
+		 */
+		fmxr(FPEXC, fpexc | FPEXC_EN);
+		vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
+		fmxr(FPEXC, fpexc);
 
-	/*
-	 * Set the context to NULL to force a reload the next time the thread
-	 * uses the VFP.
-	 */
-	last_VFP_context[cpu] = NULL;
+		/*
+		 * Set the context to NULL to force a reload the next time
+		 * the thread uses the VFP.
+		 */
+		last_VFP_context[cpu] = NULL;
+	}
 
-out:
 	put_cpu();
 }
 #endif



More information about the linux-arm-kernel mailing list