diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-03-10 10:22:35 +0000 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2009-03-10 10:22:35 +0000 |
commit | 3a078b9ac666d14152ba6362094699101ca6f2ba (patch) | |
tree | b35db95cf709ec47b969d97f04f48f472711a65d /arch/arm/vfp | |
parent | 8bd6982e2eee988d3eaf6550d24ef6e895feaeb2 (diff) |
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.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Paul Brook <paul@codesourcery.com>
Cc: Daniel Jacobowitz <dan@codesourcery.com>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r-- | arch/arm/vfp/vfp.h | 2 | ||||
-rw-r--r-- | arch/arm/vfp/vfphw.S | 2 | ||||
-rw-r--r-- | arch/arm/vfp/vfpmodule.c | 49 |
3 files changed, 49 insertions, 4 deletions
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index c85860bad585..c8c98dd44ad4 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -377,6 +377,4 @@ struct op { u32 flags; }; -#ifdef CONFIG_SMP extern void vfp_save_state(void *location, u32 fpexc); -#endif diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index a62dcf7098ba..902d3969219f 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -166,7 +166,6 @@ process_exception: @ retry the faulted instruction ENDPROC(vfp_support_entry) -#ifdef CONFIG_SMP ENTRY(vfp_save_state) @ Save the current VFP state @ r0 - save location @@ -181,7 +180,6 @@ ENTRY(vfp_save_state) stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 mov pc, lr ENDPROC(vfp_save_state) -#endif last_VFP_context_address: .word last_VFP_context diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 38b73d748919..63bf97580ccb 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -322,6 +322,55 @@ static void vfp_enable(void *unused) set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11)); } +/* + * Synchronise the hardware VFP state of a thread other than current with the + * saved one. This function is used by the ptrace mechanism. + */ +#ifdef CONFIG_SMP +void vfp_sync_state(struct thread_info *thread) +{ + /* + * On SMP systems, the VFP state is automatically saved at every + * context switch. We mark the thread VFP state as belonging to a + * non-existent CPU so that the saved one will be reloaded when + * needed. + */ + thread->vfpstate.hard.cpu = NR_CPUS; +} +#else +void vfp_sync_state(struct thread_info *thread) +{ + unsigned int cpu = get_cpu(); + u32 fpexc = fmrx(FPEXC); + + /* + * If VFP is enabled, the previous state was already saved and + * last_VFP_context updated. + */ + if (fpexc & FPEXC_EN) + goto out; + + if (!last_VFP_context[cpu]) + goto out; + + /* + * Save the last VFP state on this CPU. + */ + fmxr(FPEXC, fpexc | FPEXC_EN); + vfp_save_state(last_VFP_context[cpu], fpexc); + fmxr(FPEXC, fpexc); + + /* + * Set the context to NULL to force a reload the next time the thread + * uses the VFP. + */ + last_VFP_context[cpu] = NULL; + +out: + put_cpu(); +} +#endif + #include <linux/smp.h> /* |