1 #include <linux/kernel.h> 2 #include <linux/types.h> 3 #include <linux/thread_info.h> 4 #include <linux/uaccess.h> 5 #include <linux/errno.h> 6 7 #include <asm/sigcontext.h> 8 #include <asm/fpumacro.h> 9 #include <asm/ptrace.h> 10 11 #include "sigutil.h" 12 13 int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) 14 { 15 unsigned long *fpregs = current_thread_info()->fpregs; 16 unsigned long fprs; 17 int err = 0; 18 19 fprs = current_thread_info()->fpsaved[0]; 20 if (fprs & FPRS_DL) 21 err |= copy_to_user(&fpu->si_float_regs[0], fpregs, 22 (sizeof(unsigned int) * 32)); 23 if (fprs & FPRS_DU) 24 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, 25 (sizeof(unsigned int) * 32)); 26 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr); 27 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr); 28 err |= __put_user(fprs, &fpu->si_fprs); 29 30 return err; 31 } 32 33 int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) 34 { 35 unsigned long *fpregs = current_thread_info()->fpregs; 36 unsigned long fprs; 37 int err; 38 39 err = __get_user(fprs, &fpu->si_fprs); 40 fprs_write(0); 41 regs->tstate &= ~TSTATE_PEF; 42 if (fprs & FPRS_DL) 43 err |= copy_from_user(fpregs, &fpu->si_float_regs[0], 44 (sizeof(unsigned int) * 32)); 45 if (fprs & FPRS_DU) 46 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], 47 (sizeof(unsigned int) * 32)); 48 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); 49 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); 50 current_thread_info()->fpsaved[0] |= fprs; 51 return err; 52 } 53 54 int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin) 55 { 56 int i, err = __put_user(wsaved, &rwin->wsaved); 57 58 for (i = 0; i < wsaved; i++) { 59 struct reg_window *rp = ¤t_thread_info()->reg_window[i]; 60 unsigned long fp = current_thread_info()->rwbuf_stkptrs[i]; 61 62 err |= copy_to_user(&rwin->reg_window[i], rp, 63 sizeof(struct reg_window)); 64 err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]); 65 } 66 return err; 67 } 68 69 int restore_rwin_state(__siginfo_rwin_t __user *rp) 70 { 71 struct thread_info *t = current_thread_info(); 72 int i, wsaved, err; 73 74 __get_user(wsaved, &rp->wsaved); 75 if (wsaved > NSWINS) 76 return -EFAULT; 77 78 err = 0; 79 for (i = 0; i < wsaved; i++) { 80 err |= copy_from_user(&t->reg_window[i], 81 &rp->reg_window[i], 82 sizeof(struct reg_window)); 83 err |= __get_user(t->rwbuf_stkptrs[i], 84 &rp->rwbuf_stkptrs[i]); 85 } 86 if (err) 87 return err; 88 89 set_thread_wsaved(wsaved); 90 synchronize_user_stack(); 91 if (get_thread_wsaved()) 92 return -EFAULT; 93 return 0; 94 } 95