/* Returns positive number on error */ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { int err; _sigregs user_sregs; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); if (err) return err; regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, user_sregs.regs.psw.mask); regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr; memcpy(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, sizeof(sregs->regs.acrs)); restore_access_regs(current->thread.acrs); memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, sizeof(s390_fp_regs)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; restore_fp_regs(¤t->thread.fp_regs); regs->svcnr = 0; /* disable syscall checks */ return 0; }
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) { _s390_regs_common32 regs32; int err, i; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); if (err) return err; regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, (__u64)regs32.psw.mask << 32); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs)); restore_access_regs(current->thread.acrs); err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, sizeof(_s390_fp_regs32)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; if (err) return err; restore_fp_regs(¤t->thread.fp_regs); regs->trap = -1; /* disable syscall checks */ return 0; }
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) { _s390_regs_common32 regs32; int err, i; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); if (err) return err; regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); /* Check for invalid user address space control. */ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs)); restore_access_regs(current->thread.acrs); err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, sizeof(_s390_fp_regs32)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; if (err) return err; restore_fp_regs(¤t->thread.fp_regs); clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */ return 0; }
/* Returns positive number on error */ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { int err; _sigregs user_sregs; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); if (err) return err; /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (user_sregs.regs.psw.mask & PSW_MASK_USER); /* Check for invalid user address space control. */ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); /* Check for invalid amode */ if (regs->psw.mask & PSW_MASK_EA) regs->psw.mask |= PSW_MASK_BA; regs->psw.addr = user_sregs.regs.psw.addr; memcpy(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, sizeof(sregs->regs.acrs)); restore_access_regs(current->thread.acrs); memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, sizeof(s390_fp_regs)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; restore_fp_regs(¤t->thread.fp_regs); clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */ return 0; }
/* Returns positive number on error */ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { unsigned long old_mask = regs->psw.mask; int err; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; err = __copy_from_user(®s->psw, &sregs->regs.psw, sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs)); regs->psw.mask = PSW_MASK_MERGE(old_mask, regs->psw.mask); regs->psw.addr |= PSW_ADDR_AMODE; if (err) return err; err = __copy_from_user(¤t->thread.acrs, &sregs->regs.acrs, sizeof(sregs->regs.acrs)); if (err) return err; restore_access_regs(current->thread.acrs); err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, sizeof(s390_fp_regs)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; if (err) return err; restore_fp_regs(¤t->thread.fp_regs); regs->trap = -1; /* disable syscall checks */ return 0; }
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs) { int err = 0; s390_fp_regs fpregs; psw_t saved_psw=regs->psw; int i; for(i=0; i<NUM_GPRS; i++) err |= __get_user(regs->gprs[i], &sregs->regs.gprs[i]); for(i=0; i<NUM_ACRS; i++) err |= __get_user(regs->acrs[i], &sregs->regs.acrs[i]); err |= __copy_from_user(®s->psw.mask, &sregs->regs.psw.mask, 4); err |= __copy_from_user(((char*)®s->psw.addr)+4, &sregs->regs.psw.addr, 4); if(!err) { regs->trap = -1; /* disable syscall checks */ regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)| (regs->psw.mask&PSW_MASK_DEBUGCHANGE); regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)| (regs->psw.addr&PSW_ADDR_DEBUGCHANGE); __get_user(fpregs.fpc, &sregs->fpregs.fpc); for(i=0; i<NUM_FPRS; i++) err |= __get_user(fpregs.fprs[i].ui, &sregs->fpregs.fprs[i].d); if(!err) restore_fp_regs(&fpregs); } return(err); }
/* Load registers after signal return */ static void load_sigregs(void) { int i; restore_access_regs(current->thread.acrs); /* restore_fp_ctl is done in restore_sigregs */ if (current->thread.vxrs) { for (i = 0; i < __NUM_FPRS; i++) *(freg_t *)(current->thread.vxrs + i) = current->thread.fp_regs.fprs[i]; restore_vx_regs(current->thread.vxrs); } else restore_fp_regs(current->thread.fp_regs.fprs); }
static int restore_sigregs(struct pt_regs *regs,sigregs *sregs) { int err; s390_fp_regs fpregs; psw_t saved_psw=regs->psw; err=__copy_from_user(regs,&sregs->regs,sizeof(s390_regs_common)); if(!err) { regs->orig_gpr2 = -1; /* disable syscall checks */ regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)| (regs->psw.mask&PSW_MASK_DEBUGCHANGE); regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)| (regs->psw.addr&PSW_ADDR_DEBUGCHANGE); err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs)); if(!err) restore_fp_regs(&fpregs); } return(err); }
static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) { _sigregs32 user_sregs; int i; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs))) return -EFAULT; if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI)) return -EINVAL; /* Loading the floating-point-control word can fail. Do that first. */ if (restore_fp_ctl(&user_sregs.fpregs.fpc)) return -EINVAL; /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) | (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 | (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE); /* Check for invalid user address space control. */ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) user_sregs.regs.gprs[i]; memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, sizeof(current->thread.acrs)); restore_access_regs(current->thread.acrs); memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, sizeof(current->thread.fp_regs)); restore_fp_regs(current->thread.fp_regs.fprs); clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */ return 0; }
static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { _sigregs user_sregs; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; if (__copy_from_user(&user_sregs, sregs, sizeof(user_sregs))) return -EFAULT; if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW_MASK_RI)) return -EINVAL; /* Loading the floating-point-control word can fail. Do that first. */ if (restore_fp_ctl(&user_sregs.fpregs.fpc)) return -EINVAL; /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) | (user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI)); /* Check for invalid user address space control. */ if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME) regs->psw.mask = PSW_ASC_PRIMARY | (regs->psw.mask & ~PSW_MASK_ASC); /* Check for invalid amode */ if (regs->psw.mask & PSW_MASK_EA) regs->psw.mask |= PSW_MASK_BA; regs->psw.addr = user_sregs.regs.psw.addr; memcpy(®s->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, sizeof(current->thread.acrs)); restore_access_regs(current->thread.acrs); memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, sizeof(current->thread.fp_regs)); restore_fp_regs(current->thread.fp_regs.fprs); clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */ return 0; }