diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-02-11 13:12:56 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-02-12 10:59:43 +0000 |
commit | 3d1228ead618b88e8606015cbabc49019981805d (patch) | |
tree | 5d44c936c12ff2e99732f535dd393af201e7fe67 /arch/arm/vfp | |
parent | f373e8c0639f1720d2d0fe414990f504e113c2ba (diff) | |
download | lwn-3d1228ead618b88e8606015cbabc49019981805d.tar.gz lwn-3d1228ead618b88e8606015cbabc49019981805d.zip |
[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>
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 8de86e4feada..c8c98dd44ad4 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -377,6 +377,4 @@ struct op { u32 flags; }; -#if defined(CONFIG_SMP) || defined(CONFIG_PM) 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 c92a08bd6a86..a5a4e57763c3 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -172,7 +172,6 @@ process_exception: @ retry the faulted instruction ENDPROC(vfp_support_entry) -#if defined(CONFIG_SMP) || defined(CONFIG_PM) ENTRY(vfp_save_state) @ Save the current VFP state @ r0 - save location @@ -190,7 +189,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 9f476a1be2ca..7e1239041b39 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -377,6 +377,55 @@ static void vfp_pm_init(void) static inline void vfp_pm_init(void) { } #endif /* CONFIG_PM */ +/* + * 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> /* |