From 3d1228ead618b88e8606015cbabc49019981805d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 11 Feb 2009 13:12:56 +0100 Subject: [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 Cc: Daniel Jacobowitz Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/ptrace.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'arch/arm/kernel/ptrace.c') diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index df653ea5925..89882a1d018 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; -- cgit