in kernel/signal_64.c [41:138]
asmlinkage void sparc64_set_context(struct pt_regs *regs)
{
struct ucontext __user *ucp = (struct ucontext __user *)
regs->u_regs[UREG_I0];
enum ctx_state prev_state = exception_enter();
mc_gregset_t __user *grp;
unsigned long pc, npc, tstate;
unsigned long fp, i7;
unsigned char fenab;
int err;
synchronize_user_stack();
if (get_thread_wsaved() ||
(((unsigned long)ucp) & (sizeof(unsigned long)-1)) ||
(!__access_ok(ucp, sizeof(*ucp))))
goto do_sigsegv;
grp = &ucp->uc_mcontext.mc_gregs;
err = __get_user(pc, &((*grp)[MC_PC]));
err |= __get_user(npc, &((*grp)[MC_NPC]));
if (err || ((pc | npc) & 3))
goto do_sigsegv;
if (regs->u_regs[UREG_I1]) {
sigset_t set;
if (_NSIG_WORDS == 1) {
if (__get_user(set.sig[0], &ucp->uc_sigmask.sig[0]))
goto do_sigsegv;
} else {
if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t)))
goto do_sigsegv;
}
set_current_blocked(&set);
}
if (test_thread_flag(TIF_32BIT)) {
pc &= 0xffffffff;
npc &= 0xffffffff;
}
regs->tpc = pc;
regs->tnpc = npc;
err |= __get_user(regs->y, &((*grp)[MC_Y]));
err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));
err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));
err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));
/* Skip %g7 as that's the thread register in userspace. */
err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));
err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));
err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));
err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3]));
err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4]));
err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5]));
err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6]));
err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7]));
err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
err |= __put_user(fp,
(&(((struct reg_window __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
err |= __put_user(i7,
(&(((struct reg_window __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
if (fenab) {
unsigned long *fpregs = current_thread_info()->fpregs;
unsigned long fprs;
fprs_write(0);
err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
if (fprs & FPRS_DL)
err |= copy_from_user(fpregs,
&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
(sizeof(unsigned int) * 32));
if (fprs & FPRS_DU)
err |= copy_from_user(fpregs+16,
((unsigned long __user *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
(sizeof(unsigned int) * 32));
err |= __get_user(current_thread_info()->xfsr[0],
&(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
err |= __get_user(current_thread_info()->gsr[0],
&(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
regs->tstate &= ~TSTATE_PEF;
}
if (err)
goto do_sigsegv;
out:
exception_exit(prev_state);
return;
do_sigsegv:
force_sig(SIGSEGV);
goto out;
}