Skip to content

Commit 2af276d

Browse files
wildea01Russell King
authored andcommitted
ARM: 7306/1: vfp: flush thread hwstate before restoring context from sigframe
Following execution of a signal handler, we currently restore the VFP context from the ucontext in the signal frame. This involves copying from the user stack into the current thread's vfp_hard_struct and then flushing the new data out to the hardware registers. This is problematic when using a preemptible kernel because we could be context switched whilst updating the vfp_hard_struct. If the current thread has made use of VFP since the last context switch, the VFP notifier will copy from the hardware registers into the vfp_hard_struct, overwriting any data that had been partially copied by the signal code. Disabling preemption across copy_from_user calls is a terrible idea, so instead we move the VFP thread flush *before* we update the vfp_hard_struct. Since the flushing is performed lazily, this has the effect of disabling VFP and clearing the CPU's VFP state pointer, therefore preventing the thread from being updated with stale data on the next context switch. Cc: stable <[email protected]> Tested-by: Peter Maydell <[email protected]> Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent 97f1040 commit 2af276d

File tree

1 file changed

+2
-3
lines changed

1 file changed

+2
-3
lines changed

arch/arm/kernel/signal.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
227227
if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
228228
return -EINVAL;
229229

230+
vfp_flush_hwstate(thread);
231+
230232
/*
231233
* Copy the floating point registers. There can be unused
232234
* registers see asm/hwcap.h for details.
@@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
251253
__get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
252254
__get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
253255

254-
if (!err)
255-
vfp_flush_hwstate(thread);
256-
257256
return err ? -EFAULT : 0;
258257
}
259258

0 commit comments

Comments
 (0)