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