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