summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-03-09 14:24:05 +0000
committerian <ian@FreeBSD.org>2014-03-09 14:24:05 +0000
commit5b807dd0fd3fad9945eb48c0f326fba5f4d32dc6 (patch)
treea4bfe346436c1c9dd53e41dc88498129102fcfac /sys/arm
parentc594471e9600f3c3730f90170396dd770d6120f3 (diff)
downloadFreeBSD-src-5b807dd0fd3fad9945eb48c0f326fba5f4d32dc6.zip
FreeBSD-src-5b807dd0fd3fad9945eb48c0f326fba5f4d32dc6.tar.gz
Always call vfp_discard() on thread death, not just when the VFP is
enabled. In vfp_discard(), if the state in the VFP hardware belongs to the thread which is dying, NULL out pcpu fpcurthread to indicate the state currently in the hardware belongs to nobody. Submitted by: Juergen Weiss Pointy hat to: me
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/swtch.S9
-rw-r--r--sys/arm/arm/vfp.c18
-rw-r--r--sys/arm/include/vfp.h2
3 files changed, 14 insertions, 15 deletions
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
index 2703b03..d704823 100644
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -124,14 +124,11 @@ ENTRY(cpu_throw)
* r5 = newtd
*/
- GET_PCPU(r7, r9)
-
-#ifdef VFP
- fmrx r0, fpexc /* This thread is dying, if the VFP */
- tst r0, #(VFPEXC_EN) /* is enabled, go shut it down */
- blne _C_LABEL(vfp_discard) /* without preserving its state. */
+#ifdef VFP /* This thread is dying, disable */
+ bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
#endif
+ GET_PCPU(r7, r9)
ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
/* Switch to lwp0 context */
diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c
index d370da4..240ede3 100644
--- a/sys/arm/arm/vfp.c
+++ b/sys/arm/arm/vfp.c
@@ -229,21 +229,23 @@ vfp_store(struct vfp_state *vfpsave, boolean_t disable_vfp)
}
/*
- * If the VFP hardware is on, the current thread was using it but now that
- * thread is dying. Turn off the VFP and set pcpu fpcurthread to 0, to indicate
- * that the VFP hardware state does not belong to any thread. Called only from
- * cpu_throw(), so we don't have to worry about a context switch here.
+ * The current thread is dying. If the state currently in the hardware belongs
+ * to the current thread, set fpcurthread to NULL to indicate that the VFP
+ * hardware state does not belong to any thread. If the VFP is on, turn it off.
+ * Called only from cpu_throw(), so we don't have to worry about a context
+ * switch here.
*/
void
-vfp_discard()
+vfp_discard(struct thread *td)
{
u_int tmp;
+ if (PCPU_GET(fpcurthread) == td)
+ PCPU_SET(fpcurthread, NULL);
+
tmp = fmrx(VFPEXC);
- if (tmp & VFPEXC_EN) {
+ if (tmp & VFPEXC_EN)
fmxr(VFPEXC, tmp & ~VFPEXC_EN);
- PCPU_SET(fpcurthread, 0);
- }
}
#endif
diff --git a/sys/arm/include/vfp.h b/sys/arm/include/vfp.h
index 9023821..befba18 100644
--- a/sys/arm/include/vfp.h
+++ b/sys/arm/include/vfp.h
@@ -129,7 +129,7 @@
#ifndef LOCORE
void vfp_init(void);
void vfp_store(struct vfp_state *, boolean_t);
-void vfp_discard(void);
+void vfp_discard(struct thread *);
#endif
#endif
OpenPOWER on IntegriCloud