diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-02-11 13:12:56 +0100 |
---|---|---|
committer | Rebecca Schultz Zavin <rebecca@android.com> | 2009-10-26 12:12:05 -0700 |
commit | b15c4e90986aab12f5d93ce319c3441361478ff1 (patch) | |
tree | 5188864c9cd7396db63d0cb82fa0f8030c5a5e5c /arch/arm/kernel | |
parent | 5b1e81e05f98019eb10b80e7cc14f21a9b2906dc (diff) |
[ARM] 5387/1: Add ptrace VFP support on ARM
This patch adds ptrace support for setting and getting the VFP registers
using PTRACE_SETVFPREGS and PTRACE_GETVFPREGS. The user_vfp structure
defined in asm/user.h contains 32 double registers (to cover VFPv3 and
Neon hardware) and the FPSCR register.
Cc: Paul Brook <paul@codesourcery.com>
Cc: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
(cherry picked from commit 3d1228ead618b88e8606015cbabc49019981805d)
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/ptrace.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index df653ea59250..89882a1d0187 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -653,6 +653,54 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp) } #endif +#ifdef CONFIG_VFP +/* + * Get the child VFP state. + */ +static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data) +{ + struct thread_info *thread = task_thread_info(tsk); + union vfp_state *vfp = &thread->vfpstate; + struct user_vfp __user *ufp = data; + + vfp_sync_state(thread); + + /* copy the floating point registers */ + if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, + sizeof(vfp->hard.fpregs))) + return -EFAULT; + + /* copy the status and control register */ + if (put_user(vfp->hard.fpscr, &ufp->fpscr)) + return -EFAULT; + + return 0; +} + +/* + * Set the child VFP state. + */ +static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) +{ + struct thread_info *thread = task_thread_info(tsk); + union vfp_state *vfp = &thread->vfpstate; + struct user_vfp __user *ufp = data; + + vfp_sync_state(thread); + + /* copy the floating point registers */ + if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, + sizeof(vfp->hard.fpregs))) + return -EFAULT; + + /* copy the status and control register */ + if (get_user(vfp->hard.fpscr, &ufp->fpscr)) + return -EFAULT; + + return 0; +} +#endif + long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; @@ -775,6 +823,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; #endif +#ifdef CONFIG_VFP + case PTRACE_GETVFPREGS: + ret = ptrace_getvfpregs(child, (void __user *)data); + break; + + case PTRACE_SETVFPREGS: + ret = ptrace_setvfpregs(child, (void __user *)data); + break; +#endif + default: ret = ptrace_request(child, request, addr, data); break; |