* published by the Free Software Foundation.
*/
#include <linux/module.h>
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/init.h>
-
-#include <asm/thread_notify.h>
#include <asm/vfp.h>
#include "vfpinstr.h"
*/
unsigned int VFP_arch;
-static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
+/*
+ * Per-thread VFP initialisation.
+ */
+void vfp_flush_thread(union vfp_state *vfp)
{
- struct thread_info *thread = v;
- union vfp_state *vfp = &thread->vfpstate;
-
- switch (cmd) {
- case THREAD_NOTIFY_FLUSH:
- /*
- * Per-thread VFP initialisation.
- */
- memset(vfp, 0, sizeof(union vfp_state));
-
- vfp->hard.fpexc = FPEXC_ENABLE;
- vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
+ memset(vfp, 0, sizeof(union vfp_state));
- /*
- * Disable VFP to ensure we initialise it first.
- */
- fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
-
- /*
- * FALLTHROUGH: Ensure we don't try to overwrite our newly
- * initialised state information on the first fault.
- */
-
- case THREAD_NOTIFY_RELEASE:
- /*
- * Per-thread VFP cleanup.
- */
- if (last_VFP_context == vfp)
- last_VFP_context = NULL;
- break;
+ vfp->hard.fpexc = FPEXC_ENABLE;
+ vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
- case THREAD_NOTIFY_SWITCH:
- /*
- * Always disable VFP so we can lazily save/restore the
- * old state.
- */
- fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
- break;
- }
+ /*
+ * Disable VFP to ensure we initialise it first.
+ */
+ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
- return NOTIFY_DONE;
+ /*
+ * Ensure we don't try to overwrite our newly initialised
+ * state information on the first fault.
+ */
+ if (last_VFP_context == vfp)
+ last_VFP_context = NULL;
}
-static struct notifier_block vfp_notifier_block = {
- .notifier_call = vfp_notifier,
-};
+/*
+ * Per-thread VFP cleanup.
+ */
+void vfp_release_thread(union vfp_state *vfp)
+{
+ if (last_VFP_context == vfp)
+ last_VFP_context = NULL;
+}
/*
* Raise a SIGFPE for the current process.
pr_debug("VFP: raising exceptions %08x\n", exceptions);
- if (exceptions == VFP_EXCEPTION_ERROR) {
+ if (exceptions == (u32)-1) {
vfp_panic("unhandled bounce");
vfp_raise_sigfpe(0, regs);
return;
*/
static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
{
- u32 exceptions = VFP_EXCEPTION_ERROR;
+ u32 exceptions = (u32)-1;
pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr);
* emulate it.
*/
}
- return exceptions & ~VFP_NAN_FLAG;
+ return exceptions;
}
/*
*/
barrier();
trigger = fmrx(FPINST2);
- orig_fpscr = fpscr = fmrx(FPSCR);
+ fpscr = fmrx(FPSCR);
emulate:
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
(vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
(vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
vfp_vector = vfp_support_entry;
-
- thread_register_notifier(&vfp_notifier_block);
}
return 0;
}