/* Returns non-zero on fault. */ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { _sigregs user_sregs; save_access_regs(current->thread.acrs); /* Copy a 'clean' PSW mask to the user to avoid leaking information about whether PER is currently on. */ user_sregs.regs.psw.mask = PSW_USER_BITS | (regs->psw.mask & (PSW_MASK_USER | PSW_MASK_RI)); user_sregs.regs.psw.addr = regs->psw.addr; memcpy(&user_sregs.regs.gprs, ®s->gprs, sizeof(sregs->regs.gprs)); memcpy(&user_sregs.regs.acrs, current->thread.acrs, sizeof(user_sregs.regs.acrs)); /* * We have to store the fp registers to current->thread.fp_regs * to merge them with the emulated registers. */ save_fp_ctl(¤t->thread.fp_regs.fpc); save_fp_regs(current->thread.fp_regs.fprs); memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, sizeof(user_sregs.fpregs)); if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs))) return -EFAULT; return 0; }
/* Returns non-zero on fault. */ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { unsigned long old_mask = regs->psw.mask; int err; save_access_regs(current->thread.acrs); /* Copy a 'clean' PSW mask to the user to avoid leaking information about whether PER is currently on. */ regs->psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask); err = __copy_to_user(&sregs->regs.psw, ®s->psw, sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs)); regs->psw.mask = old_mask; if (err != 0) return err; err = __copy_to_user(&sregs->regs.acrs, current->thread.acrs, sizeof(sregs->regs.acrs)); if (err != 0) return err; /* * We have to store the fp registers to current->thread.fp_regs * to merge them with the emulated registers. */ save_fp_regs(¤t->thread.fp_regs); return __copy_to_user(&sregs->fpregs, ¤t->thread.fp_regs, sizeof(s390_fp_regs)); }
static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) { if (tsk == current) save_fp_regs((s390_fp_regs *)fpregs); else memcpy(fpregs, &tsk->thread.fp_regs, sizeof(elf_fpregset_t)); return 1; }
/* Store registers needed to create the signal frame */ static void store_sigregs(void) { int i; save_access_regs(current->thread.acrs); save_fp_ctl(¤t->thread.fp_regs.fpc); if (current->thread.vxrs) { save_vx_regs(current->thread.vxrs); for (i = 0; i < __NUM_FPRS; i++) current->thread.fp_regs.fprs[i] = *(freg_t *)(current->thread.vxrs + i); } else save_fp_regs(current->thread.fp_regs.fprs); }
static int save_sigregs(struct pt_regs *regs,sigregs *sregs) { int err; s390_fp_regs fpregs; err = __copy_to_user(&sregs->regs,regs,sizeof(s390_regs_common)); if(!err) { save_fp_regs(&fpregs); err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs)); } return(err); }
static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) { _s390_regs_common32 regs32; int err, i; regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits, (__u32)(regs->psw.mask >> 32)); regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr; for (i = 0; i < NUM_GPRS; i++) regs32.gprs[i] = (__u32) regs->gprs[i]; save_access_regs(current->thread.acrs); memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs)); err = __copy_to_user(&sregs->regs, ®s32, sizeof(regs32)); if (err) return err; save_fp_regs(¤t->thread.fp_regs); /* s390_fp_regs and _s390_fp_regs32 are the same ! */ return __copy_to_user(&sregs->fpregs, ¤t->thread.fp_regs, sizeof(_s390_fp_regs32)); }
/* Returns non-zero on fault. */ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { _sigregs user_sregs; save_access_regs(current->thread.acrs); /* Copy a 'clean' PSW mask to the user to avoid leaking information about whether PER is currently on. */ user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask); user_sregs.regs.psw.addr = regs->psw.addr; memcpy(&user_sregs.regs.gprs, ®s->gprs, sizeof(sregs->regs.gprs)); memcpy(&user_sregs.regs.acrs, current->thread.acrs, sizeof(sregs->regs.acrs)); /* * We have to store the fp registers to current->thread.fp_regs * to merge them with the emulated registers. */ save_fp_regs(¤t->thread.fp_regs); memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, sizeof(s390_fp_regs)); return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs)); }
static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs) { int err = 0; s390_fp_regs fpregs; int i; for(i=0; i<NUM_GPRS; i++) err |= __put_user(regs->gprs[i], &sregs->regs.gprs[i]); for(i=0; i<NUM_ACRS; i++) err |= __put_user(regs->acrs[i], &sregs->regs.acrs[i]); err |= __copy_to_user(&sregs->regs.psw.mask, ®s->psw.mask, 4); err |= __copy_to_user(&sregs->regs.psw.addr, ((char*)®s->psw.addr)+4, 4); if(!err) { save_fp_regs(&fpregs); __put_user(fpregs.fpc, &sregs->fpregs.fpc); for(i=0; i<NUM_FPRS; i++) err |= __put_user(fpregs.fprs[i].ui, &sregs->fpregs.fprs[i].d); } return(err); }
static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) { _sigregs32 user_sregs; int i; user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32); user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI; user_sregs.regs.psw.mask |= psw32_user_bits; user_sregs.regs.psw.addr = (__u32) regs->psw.addr | (__u32)(regs->psw.mask & PSW_MASK_BA); for (i = 0; i < NUM_GPRS; i++) user_sregs.regs.gprs[i] = (__u32) regs->gprs[i]; save_access_regs(current->thread.acrs); memcpy(&user_sregs.regs.acrs, current->thread.acrs, sizeof(user_sregs.regs.acrs)); save_fp_ctl(¤t->thread.fp_regs.fpc); save_fp_regs(current->thread.fp_regs.fprs); memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, sizeof(user_sregs.fpregs)); if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32))) return -EFAULT; return 0; }
int copy_thread(unsigned long clone_flags, unsigned long new_stackp, unsigned long arg, struct task_struct *p) { struct thread_info *ti; struct fake_frame { struct stack_frame sf; struct pt_regs childregs; } *frame; frame = container_of(task_pt_regs(p), struct fake_frame, childregs); p->thread.ksp = (unsigned long) frame; /* Save access registers to new thread structure. */ save_access_regs(&p->thread.acrs[0]); /* start new process with ar4 pointing to the correct address space */ p->thread.mm_segment = get_fs(); /* Don't copy debug registers */ memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); clear_tsk_thread_flag(p, TIF_SINGLE_STEP); /* Initialize per thread user and system timer values */ ti = task_thread_info(p); ti->user_timer = 0; ti->system_timer = 0; frame->sf.back_chain = 0; /* new return point is ret_from_fork */ frame->sf.gprs[8] = (unsigned long) ret_from_fork; /* fake return stack for resume(), don't go back to schedule */ frame->sf.gprs[9] = (unsigned long) frame; /* Store access registers to kernel stack of new process. */ if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ memset(&frame->childregs, 0, sizeof(struct pt_regs)); frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; frame->childregs.psw.addr = PSW_ADDR_AMODE | (unsigned long) kernel_thread_starter; frame->childregs.gprs[9] = new_stackp; /* function */ frame->childregs.gprs[10] = arg; frame->childregs.gprs[11] = (unsigned long) do_exit; frame->childregs.orig_gpr2 = -1; return 0; } frame->childregs = *current_pt_regs(); frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ frame->childregs.flags = 0; if (new_stackp) frame->childregs.gprs[15] = new_stackp; /* Don't copy runtime instrumentation info */ p->thread.ri_cb = NULL; p->thread.ri_signum = 0; frame->childregs.psw.mask &= ~PSW_MASK_RI; #ifndef CONFIG_64BIT /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the child. */ save_fp_ctl(¤t->thread.fp_regs.fpc); save_fp_regs(current->thread.fp_regs.fprs); memcpy(&p->thread.fp_regs, ¤t->thread.fp_regs, sizeof(s390_fp_regs)); /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) p->thread.acrs[0] = frame->childregs.gprs[6]; #else /* CONFIG_64BIT */ /* Save the fpu registers to new thread structure. */ save_fp_ctl(&p->thread.fp_regs.fpc); save_fp_regs(p->thread.fp_regs.fprs); p->thread.fp_regs.pad = 0; /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) { unsigned long tls = frame->childregs.gprs[6]; if (is_compat_task()) { p->thread.acrs[0] = (unsigned int)tls; } else { p->thread.acrs[0] = (unsigned int)(tls >> 32); p->thread.acrs[1] = (unsigned int)tls; } }