aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-04-23 10:38:28 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-04-23 10:44:41 -0400
commit2498814fcb3068f19b82b1519b4038721f61af43 (patch)
tree6a3483bab350438a768b56bb56611d609b2396b4 /arch/arm/vfp
parentab4d536890853ab6675ede65db40e2c0980cb0ea (diff)
ARM: 7399/1: vfp: move user vfp state save/restore code out of signal.c
The user VFP state must be preserved (subject to ucontext modifications) across invocation of a signal handler and this is currently handled by vfp_{preserve,restore}_context in signal.c Since this code requires intimate low-level knowledge of the VFP state, this patch moves it into vfpmodule.c. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r--arch/arm/vfp/vfpmodule.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 858748eaa144..05872d92fca2 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -17,6 +17,8 @@
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/smp.h> 18#include <linux/smp.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/uaccess.h>
21#include <linux/user.h>
20 22
21#include <asm/cp15.h> 23#include <asm/cp15.h>
22#include <asm/cputype.h> 24#include <asm/cputype.h>
@@ -529,6 +531,83 @@ void vfp_flush_hwstate(struct thread_info *thread)
529} 531}
530 532
531/* 533/*
534 * Save the current VFP state into the provided structures and prepare
535 * for entry into a new function (signal handler).
536 */
537int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
538 struct user_vfp_exc __user *ufp_exc)
539{
540 struct thread_info *thread = current_thread_info();
541 struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
542 int err = 0;
543
544 /* Ensure that the saved hwstate is up-to-date. */
545 vfp_sync_hwstate(thread);
546
547 /*
548 * Copy the floating point registers. There can be unused
549 * registers see asm/hwcap.h for details.
550 */
551 err |= __copy_to_user(&ufp->fpregs, &hwstate->fpregs,
552 sizeof(hwstate->fpregs));
553 /*
554 * Copy the status and control register.
555 */
556 __put_user_error(hwstate->fpscr, &ufp->fpscr, err);
557
558 /*
559 * Copy the exception registers.
560 */
561 __put_user_error(hwstate->fpexc, &ufp_exc->fpexc, err);
562 __put_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
563 __put_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
564
565 if (err)
566 return -EFAULT;
567 return 0;
568}
569
570/* Sanitise and restore the current VFP state from the provided structures. */
571int vfp_restore_user_hwstate(struct user_vfp __user *ufp,
572 struct user_vfp_exc __user *ufp_exc)
573{
574 struct thread_info *thread = current_thread_info();
575 struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
576 unsigned long fpexc;
577 int err = 0;
578
579 vfp_flush_hwstate(thread);
580
581 /*
582 * Copy the floating point registers. There can be unused
583 * registers see asm/hwcap.h for details.
584 */
585 err |= __copy_from_user(&hwstate->fpregs, &ufp->fpregs,
586 sizeof(hwstate->fpregs));
587 /*
588 * Copy the status and control register.
589 */
590 __get_user_error(hwstate->fpscr, &ufp->fpscr, err);
591
592 /*
593 * Sanitise and restore the exception registers.
594 */
595 __get_user_error(fpexc, &ufp_exc->fpexc, err);
596
597 /* Ensure the VFP is enabled. */
598 fpexc |= FPEXC_EN;
599
600 /* Ensure FPINST2 is invalid and the exception flag is cleared. */
601 fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
602 hwstate->fpexc = fpexc;
603
604 __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
605 __get_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
606
607 return err ? -EFAULT : 0;
608}
609
610/*
532 * VFP hardware can lose all context when a CPU goes offline. 611 * VFP hardware can lose all context when a CPU goes offline.
533 * As we will be running in SMP mode with CPU hotplug, we will save the 612 * As we will be running in SMP mode with CPU hotplug, we will save the
534 * hardware state at every thread switch. We clear our held state when 613 * hardware state at every thread switch. We clear our held state when