diff options
Diffstat (limited to 'arch/openrisc/kernel/signal.c')
| -rw-r--r-- | arch/openrisc/kernel/signal.c | 36 | 
1 files changed, 34 insertions, 2 deletions
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index e2f21a5d8ad9..c7ab42e2cb7a 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -23,6 +23,7 @@  #include <linux/stddef.h>  #include <linux/resume_user_mode.h> +#include <asm/fpu.h>  #include <asm/processor.h>  #include <asm/syscall.h>  #include <asm/ucontext.h> @@ -39,6 +40,37 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs);  asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags,  			       int syscall); +#ifdef CONFIG_FPU +static long restore_fp_state(struct sigcontext __user *sc) +{ +	long err; + +	err = __copy_from_user(¤t->thread.fpcsr, &sc->fpcsr, sizeof(unsigned long)); +	if (unlikely(err)) +		return err; + +	/* Restore the FPU state */ +	restore_fpu(current); + +	return 0; +} + +static long save_fp_state(struct sigcontext __user *sc) +{ +	long err; + +	/* Sync the user FPU state so we can copy to sigcontext */ +	save_fpu(current); + +	err = __copy_to_user(&sc->fpcsr, ¤t->thread.fpcsr, sizeof(unsigned long)); + +	return err; +} +#else +#define save_fp_state(sc) (0) +#define restore_fp_state(sc) (0) +#endif +  static int restore_sigcontext(struct pt_regs *regs,  			      struct sigcontext __user *sc)  { @@ -55,7 +87,7 @@ static int restore_sigcontext(struct pt_regs *regs,  	err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));  	err |= __copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long));  	err |= __copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long)); -	err |= __copy_from_user(®s->fpcsr, &sc->fpcsr, sizeof(unsigned long)); +	err |= restore_fp_state(sc);  	/* make sure the SM-bit is cleared so user-mode cannot fool us */  	regs->sr &= ~SPR_SR_SM; @@ -118,7 +150,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)  	err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));  	err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long));  	err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long)); -	err |= __copy_to_user(&sc->fpcsr, ®s->fpcsr, sizeof(unsigned long)); +	err |= save_fp_state(sc);  	return err;  }  |