|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/uaccess.h>
|
|
|
#include <linux/user.h>
|
|
|
+#include <linux/export.h>
|
|
|
|
|
|
#include <asm/cp15.h>
|
|
|
#include <asm/cputype.h>
|
|
@@ -668,6 +669,52 @@ void vfp_kmode_exception(void)
|
|
|
pr_crit("BUG: FP instruction issued in kernel mode with FP unit disabled\n");
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_KERNEL_MODE_NEON
|
|
|
+
|
|
|
+/*
|
|
|
+ * Kernel-side NEON support functions
|
|
|
+ */
|
|
|
+void kernel_neon_begin(void)
|
|
|
+{
|
|
|
+ struct thread_info *thread = current_thread_info();
|
|
|
+ unsigned int cpu;
|
|
|
+ u32 fpexc;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Kernel mode NEON is only allowed outside of interrupt context
|
|
|
+ * with preemption disabled. This will make sure that the kernel
|
|
|
+ * mode NEON register contents never need to be preserved.
|
|
|
+ */
|
|
|
+ BUG_ON(in_interrupt());
|
|
|
+ cpu = get_cpu();
|
|
|
+
|
|
|
+ fpexc = fmrx(FPEXC) | FPEXC_EN;
|
|
|
+ fmxr(FPEXC, fpexc);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Save the userland NEON/VFP state. Under UP,
|
|
|
+ * the owner could be a task other than 'current'
|
|
|
+ */
|
|
|
+ if (vfp_state_in_hw(cpu, thread))
|
|
|
+ vfp_save_state(&thread->vfpstate, fpexc);
|
|
|
+#ifndef CONFIG_SMP
|
|
|
+ else if (vfp_current_hw_state[cpu] != NULL)
|
|
|
+ vfp_save_state(vfp_current_hw_state[cpu], fpexc);
|
|
|
+#endif
|
|
|
+ vfp_current_hw_state[cpu] = NULL;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(kernel_neon_begin);
|
|
|
+
|
|
|
+void kernel_neon_end(void)
|
|
|
+{
|
|
|
+ /* Disable the NEON/VFP unit. */
|
|
|
+ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
|
|
+ put_cpu();
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(kernel_neon_end);
|
|
|
+
|
|
|
+#endif /* CONFIG_KERNEL_MODE_NEON */
|
|
|
+
|
|
|
/*
|
|
|
* VFP support code initialisation.
|
|
|
*/
|