/* * This does just the minimum required setup of sigcontext. * Specifically, it only installs data that is either not knowable at * the user-level or that gets modified before execution in the * trampoline starts. Everything else is done at the user-level. */ static long setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr) { unsigned long flags = 0, ifs, cfm, nat; long err; ifs = scr->pt.cr_ifs; if (on_sig_stack((unsigned long) sc)) flags |= IA64_SC_FLAG_ONSTACK; if ((ifs & (1UL << 63)) == 0) /* if cr_ifs doesn't have the valid bit set, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); } nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat); err = __put_user(flags, &sc->sc_flags); err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); err |= __put_user(cfm, &sc->sc_cfm); err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __put_user(scr->pt.ar_unat, &sc->sc_ar_unat); /* ar.unat */ err |= __put_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); /* ar.fpsr */ err |= __put_user(scr->pt.ar_pfs, &sc->sc_ar_pfs); err |= __put_user(scr->pt.pr, &sc->sc_pr); /* predicates */ err |= __put_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */ err |= __put_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */ err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 8); /* r1 */ err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8); /* r8-r11 */ err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 2*8); /* r12-r13 */ err |= __copy_to_user(&sc->sc_gr[15], &scr->pt.r15, 8); /* r15 */ err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip); if (flags & IA64_SC_FLAG_IN_SYSCALL) { /* Clear scratch registers if the signal interrupted a system call. */ err |= __put_user(0, &sc->sc_ar_ccv); /* ar.ccv */ err |= __put_user(0, &sc->sc_br[7]); /* b7 */ err |= __put_user(0, &sc->sc_gr[14]); /* r14 */ err |= __clear_user(&sc->sc_ar25, 2*8); /* ar.csd & ar.ssd */ err |= __clear_user(&sc->sc_gr[2], 2*8); /* r2-r3 */ err |= __clear_user(&sc->sc_gr[16], 16*8); /* r16-r31 */ } else { /* Copy scratch regs to sigcontext if the signal didn't interrupt a syscall. */ err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); /* ar.ccv */ err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ err |= __put_user(scr->pt.r14, &sc->sc_gr[14]); /* r14 */ err |= __copy_to_user(&sc->sc_ar25, &scr->pt.ar_csd, 2*8); /* ar.csd & ar.ssd */ err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8); /* r2-r3 */ err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */ } return err; }
/* * This does just the minimum required setup of sigcontext. * Specifically, it only installs data that is either not knowable at * the user-level or that gets modified before execution in the * trampoline starts. Everything else is done at the user-level. */ static long setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) { unsigned long flags = 0, ifs, cfm, nat; long err; ifs = scr->pt.cr_ifs; if (on_sig_stack((unsigned long) sc)) flags |= IA64_SC_FLAG_ONSTACK; if ((ifs & (1UL << 63)) == 0) { /* if cr_ifs isn't valid, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; cfm = scr->pad & ((1UL << 38) - 1); } else cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); } /* * Note: sw->ar_unat is UNDEFINED unless the process is being * PTRACED. However, this is OK because the NaT bits of the * preserved registers (r4-r7) are never being looked at by * the signal handler (registers r4-r7 are used instead). */ nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat); err = __put_user(flags, &sc->sc_flags); err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); err |= __put_user(cfm, &sc->sc_cfm); err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); err |= __put_user(scr->pt.ar_unat, &sc->sc_ar_unat); /* ar.unat */ err |= __put_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); /* ar.fpsr */ err |= __put_user(scr->pt.ar_pfs, &sc->sc_ar_pfs); err |= __put_user(scr->pt.pr, &sc->sc_pr); /* predicates */ err |= __put_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */ err |= __put_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */ err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 3*8); /* r1-r3 */ err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8); /* r8-r11 */ err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 4*8); /* r12-r15 */ err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */ err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip); return err; }