Skip to content

Commit

Permalink
ARM: vfp ptrace: no point flushing hw context for PTRACE_GETVFPREGS
Browse files Browse the repository at this point in the history
If we're only reading the VFP context via the ptrace call, there's
no need to invalidate the hardware context - we only need to do that
on PTRACE_SETVFPREGS.  This allows more efficient monitoring of a
traced task.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Russell King committed Feb 15, 2010
1 parent 54cb3db commit ad187f9
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
3 changes: 2 additions & 1 deletion arch/arm/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
extern void iwmmxt_task_release(struct thread_info *);
extern void iwmmxt_task_switch(struct thread_info *);

extern void vfp_sync_state(struct thread_info *thread);
extern void vfp_sync_hwstate(struct thread_info *);
extern void vfp_flush_hwstate(struct thread_info *);

#endif

Expand Down
6 changes: 4 additions & 2 deletions arch/arm/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
union vfp_state *vfp = &thread->vfpstate;
struct user_vfp __user *ufp = data;

vfp_sync_state(thread);
vfp_sync_hwstate(thread);

/* copy the floating point registers */
if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
Expand All @@ -723,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
union vfp_state *vfp = &thread->vfpstate;
struct user_vfp __user *ufp = data;

vfp_sync_state(thread);
vfp_sync_hwstate(thread);

/* copy the floating point registers */
if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
Expand All @@ -734,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
if (get_user(vfp->hard.fpscr, &ufp->fpscr))
return -EFAULT;

vfp_flush_hwstate(thread);

return 0;
}
#endif
Expand Down
25 changes: 23 additions & 2 deletions arch/arm/vfp/vfpmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,11 @@ static inline void vfp_pm_init(void) { }
* saved one. This function is used by the ptrace mechanism.
*/
#ifdef CONFIG_SMP
void vfp_sync_state(struct thread_info *thread)
void vfp_sync_hwstate(struct thread_info *thread)
{
}

void vfp_flush_hwstate(struct thread_info *thread)
{
/*
* On SMP systems, the VFP state is automatically saved at every
Expand All @@ -441,7 +445,7 @@ void vfp_sync_state(struct thread_info *thread)
thread->vfpstate.hard.cpu = NR_CPUS;
}
#else
void vfp_sync_state(struct thread_info *thread)
void vfp_sync_hwstate(struct thread_info *thread)
{
unsigned int cpu = get_cpu();

Expand All @@ -457,6 +461,23 @@ void vfp_sync_state(struct thread_info *thread)
*/
fmxr(FPEXC, fpexc | FPEXC_EN);
vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
fmxr(FPEXC, fpexc);
}

put_cpu();
}

void vfp_flush_hwstate(struct thread_info *thread)
{
unsigned int cpu = get_cpu();

/*
* If the thread we're interested in is the current owner of the
* hardware VFP state, then we need to save its state.
*/
if (last_VFP_context[cpu] == &thread->vfpstate) {
u32 fpexc = fmrx(FPEXC);

fmxr(FPEXC, fpexc & ~FPEXC_EN);

/*
Expand Down

0 comments on commit ad187f9

Please sign in to comment.