aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-06-21 08:31:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-22 05:24:18 -0400
commitd6551e884cf66de072b81f8b6d23259462c40baf (patch)
treefd8af193bd045e4b16ce911d392d7ffd109d7284 /arch/arm/vfp
parent52ab3f3dc711eeccbfbcc5d4f5c5d9b9ff59650f (diff)
[ARM] Add thread_notify infrastructure
Some machine classes need to allow VFP support to be built into the kernel, but still allow the kernel to run even though VFP isn't present. Unfortunately, the kernel hard-codes VFP instructions into the thread switch, which prevents this being run-time selectable. Solve this by introducing a notifier which things such as VFP can hook into to be informed of events which affect the VFP subsystem (eg, creation and destruction of threads, switches between threads.) Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r--arch/arm/vfp/vfpmodule.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 03486be04193..2476f4c2e760 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -15,6 +15,8 @@
15#include <linux/signal.h> 15#include <linux/signal.h>
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/init.h> 17#include <linux/init.h>
18
19#include <asm/thread_notify.h>
18#include <asm/vfp.h> 20#include <asm/vfp.h>
19 21
20#include "vfpinstr.h" 22#include "vfpinstr.h"
@@ -36,38 +38,55 @@ union vfp_state *last_VFP_context;
36 */ 38 */
37unsigned int VFP_arch; 39unsigned int VFP_arch;
38 40
39/* 41static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
40 * Per-thread VFP initialisation.
41 */
42void vfp_flush_thread(union vfp_state *vfp)
43{ 42{
44 memset(vfp, 0, sizeof(union vfp_state)); 43 struct thread_info *thread = v;
44 union vfp_state *vfp = &thread->vfpstate;
45 45
46 vfp->hard.fpexc = FPEXC_ENABLE; 46 switch (cmd) {
47 vfp->hard.fpscr = FPSCR_ROUND_NEAREST; 47 case THREAD_NOTIFY_FLUSH:
48 /*
49 * Per-thread VFP initialisation.
50 */
51 memset(vfp, 0, sizeof(union vfp_state));
48 52
49 /* 53 vfp->hard.fpexc = FPEXC_ENABLE;
50 * Disable VFP to ensure we initialise it first. 54 vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
51 */
52 fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
53 55
54 /* 56 /*
55 * Ensure we don't try to overwrite our newly initialised 57 * Disable VFP to ensure we initialise it first.
56 * state information on the first fault. 58 */
57 */ 59 fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
58 if (last_VFP_context == vfp)
59 last_VFP_context = NULL;
60}
61 60
62/* 61 /*
63 * Per-thread VFP cleanup. 62 * FALLTHROUGH: Ensure we don't try to overwrite our newly
64 */ 63 * initialised state information on the first fault.
65void vfp_release_thread(union vfp_state *vfp) 64 */
66{ 65
67 if (last_VFP_context == vfp) 66 case THREAD_NOTIFY_RELEASE:
68 last_VFP_context = NULL; 67 /*
68 * Per-thread VFP cleanup.
69 */
70 if (last_VFP_context == vfp)
71 last_VFP_context = NULL;
72 break;
73
74 case THREAD_NOTIFY_SWITCH:
75 /*
76 * Always disable VFP so we can lazily save/restore the
77 * old state.
78 */
79 fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
80 break;
81 }
82
83 return NOTIFY_DONE;
69} 84}
70 85
86static struct notifier_block vfp_notifier_block = {
87 .notifier_call = vfp_notifier,
88};
89
71/* 90/*
72 * Raise a SIGFPE for the current process. 91 * Raise a SIGFPE for the current process.
73 * sicode describes the signal being raised. 92 * sicode describes the signal being raised.
@@ -281,6 +300,8 @@ static int __init vfp_init(void)
281 (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, 300 (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
282 (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); 301 (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
283 vfp_vector = vfp_support_entry; 302 vfp_vector = vfp_support_entry;
303
304 thread_register_notifier(&vfp_notifier_block);
284 } 305 }
285 return 0; 306 return 0;
286} 307}