ARM: 8791/1: vfp: use __copy_to_user() when saving VFP state
Use __copy_to_user() rather than __put_user_error() for individual members when saving VFP state. This has the benefit of disabling/enabling PAN once per copied struct intead of once per write. Signed-off-by: Julien Thierry <julien.thierry@arm.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
Родитель
73839798af
Коммит
3aa2df6ec2
|
@ -121,8 +121,8 @@ extern void vfp_flush_hwstate(struct thread_info *);
|
||||||
struct user_vfp;
|
struct user_vfp;
|
||||||
struct user_vfp_exc;
|
struct user_vfp_exc;
|
||||||
|
|
||||||
extern int vfp_preserve_user_clear_hwstate(struct user_vfp __user *,
|
extern int vfp_preserve_user_clear_hwstate(struct user_vfp *,
|
||||||
struct user_vfp_exc __user *);
|
struct user_vfp_exc *);
|
||||||
extern int vfp_restore_user_hwstate(struct user_vfp *,
|
extern int vfp_restore_user_hwstate(struct user_vfp *,
|
||||||
struct user_vfp_exc *);
|
struct user_vfp_exc *);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -137,17 +137,18 @@ static int restore_iwmmxt_context(char __user **auxp)
|
||||||
|
|
||||||
static int preserve_vfp_context(struct vfp_sigframe __user *frame)
|
static int preserve_vfp_context(struct vfp_sigframe __user *frame)
|
||||||
{
|
{
|
||||||
const unsigned long magic = VFP_MAGIC;
|
struct vfp_sigframe kframe;
|
||||||
const unsigned long size = VFP_STORAGE_SIZE;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
__put_user_error(magic, &frame->magic, err);
|
memset(&kframe, 0, sizeof(kframe));
|
||||||
__put_user_error(size, &frame->size, err);
|
kframe.magic = VFP_MAGIC;
|
||||||
|
kframe.size = VFP_STORAGE_SIZE;
|
||||||
|
|
||||||
|
err = vfp_preserve_user_clear_hwstate(&kframe.ufp, &kframe.ufp_exc);
|
||||||
if (err)
|
if (err)
|
||||||
return -EFAULT;
|
return err;
|
||||||
|
|
||||||
return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc);
|
return __copy_to_user(frame, &kframe, sizeof(kframe));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int restore_vfp_context(char __user **auxp)
|
static int restore_vfp_context(char __user **auxp)
|
||||||
|
|
|
@ -554,12 +554,11 @@ void vfp_flush_hwstate(struct thread_info *thread)
|
||||||
* Save the current VFP state into the provided structures and prepare
|
* Save the current VFP state into the provided structures and prepare
|
||||||
* for entry into a new function (signal handler).
|
* for entry into a new function (signal handler).
|
||||||
*/
|
*/
|
||||||
int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
|
int vfp_preserve_user_clear_hwstate(struct user_vfp *ufp,
|
||||||
struct user_vfp_exc __user *ufp_exc)
|
struct user_vfp_exc *ufp_exc)
|
||||||
{
|
{
|
||||||
struct thread_info *thread = current_thread_info();
|
struct thread_info *thread = current_thread_info();
|
||||||
struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
|
struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
/* Ensure that the saved hwstate is up-to-date. */
|
/* Ensure that the saved hwstate is up-to-date. */
|
||||||
vfp_sync_hwstate(thread);
|
vfp_sync_hwstate(thread);
|
||||||
|
@ -568,22 +567,19 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
|
||||||
* Copy the floating point registers. There can be unused
|
* Copy the floating point registers. There can be unused
|
||||||
* registers see asm/hwcap.h for details.
|
* registers see asm/hwcap.h for details.
|
||||||
*/
|
*/
|
||||||
err |= __copy_to_user(&ufp->fpregs, &hwstate->fpregs,
|
memcpy(&ufp->fpregs, &hwstate->fpregs, sizeof(hwstate->fpregs));
|
||||||
sizeof(hwstate->fpregs));
|
|
||||||
/*
|
/*
|
||||||
* Copy the status and control register.
|
* Copy the status and control register.
|
||||||
*/
|
*/
|
||||||
__put_user_error(hwstate->fpscr, &ufp->fpscr, err);
|
ufp->fpscr = hwstate->fpscr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the exception registers.
|
* Copy the exception registers.
|
||||||
*/
|
*/
|
||||||
__put_user_error(hwstate->fpexc, &ufp_exc->fpexc, err);
|
ufp_exc->fpexc = hwstate->fpexc;
|
||||||
__put_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
|
ufp_exc->fpinst = hwstate->fpinst;
|
||||||
__put_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
|
ufp_exc->fpinst2 = ufp_exc->fpinst2;
|
||||||
|
|
||||||
if (err)
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
/* Ensure that VFP is disabled. */
|
/* Ensure that VFP is disabled. */
|
||||||
vfp_flush_hwstate(thread);
|
vfp_flush_hwstate(thread);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче