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 if (((unsigned long) fpu) & 7) 41 return -EFAULT; 42 43 err = get_user(fprs, &fpu->si_fprs); 44 fprs_write(0); 45 regs->tstate &= ~TSTATE_PEF; 46 if (fprs & FPRS_DL) 47 err |= copy_from_user(fpregs, &fpu->si_float_regs[0], 48 (sizeof(unsigned int) * 32)); 49 if (fprs & FPRS_DU) 50 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], 51 (sizeof(unsigned int) * 32)); 52 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr); 53 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr); 54 current_thread_info()->fpsaved[0] |= fprs; 55 return err; 56 } 57 58 int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin) 59 { 60 int i, err = __put_user(wsaved, &rwin->wsaved); 61 62 for (i = 0; i < wsaved; i++) { 63 struct reg_window *rp = ¤t_thread_info()->reg_window[i]; 64 unsigned long fp = current_thread_info()->rwbuf_stkptrs[i]; 65 66 err |= copy_to_user(&rwin->reg_window[i], rp, 67 sizeof(struct reg_window)); 68 err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]); 69 } 70 return err; 71 } 72 73 int restore_rwin_state(__siginfo_rwin_t __user *rp) 74 { 75 struct thread_info *t = current_thread_info(); 76 int i, wsaved, err; 77 78 if (((unsigned long) rp) & 7) 79 return -EFAULT; 80 81 get_user(wsaved, &rp->wsaved); 82 if (wsaved > NSWINS) 83 return -EFAULT; 84 85 err = 0; 86 for (i = 0; i < wsaved; i++) { 87 err |= copy_from_user(&t->reg_window[i], 88 &rp->reg_window[i], 89 sizeof(struct reg_window)); 90 err |= __get_user(t->rwbuf_stkptrs[i], 91 &rp->rwbuf_stkptrs[i]); 92 } 93 if (err) 94 return err; 95 96 set_thread_wsaved(wsaved); 97 synchronize_user_stack(); 98 if (get_thread_wsaved()) 99 return -EFAULT; 100 return 0; 101 } 102