int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs) { mcontext_t *dst_tc = &sigframe->uc_transact.uc_mcontext; mcontext_t *dst = &sigframe->uc.uc_mcontext; if (fpregs->flags & USER_FPREGS_FL_TM) { prep_gp_regs(&sigframe->uc_transact.uc_mcontext, &fpregs->tm.regs); prep_gp_regs(&sigframe->uc.uc_mcontext, &fpregs->tm.regs); } else { prep_gp_regs(&sigframe->uc.uc_mcontext, regs); } if (fpregs->flags & USER_FPREGS_FL_TM) sigframe->uc.uc_link = &sigframe->uc_transact; if (fpregs->flags & USER_FPREGS_FL_FP) { if (fpregs->flags & USER_FPREGS_FL_TM) { put_fpu_regs(&sigframe->uc_transact.uc_mcontext, fpregs->tm.fpregs); put_fpu_regs(&sigframe->uc.uc_mcontext, fpregs->tm.fpregs); } else { put_fpu_regs(&sigframe->uc.uc_mcontext, fpregs->fpregs); } } if (fpregs->flags & USER_FPREGS_FL_ALTIVEC) { if (fpregs->flags & USER_FPREGS_FL_TM) { put_altivec_regs(&sigframe->uc_transact.uc_mcontext, fpregs->tm.vrregs); put_altivec_regs(&sigframe->uc.uc_mcontext, fpregs->tm.vrregs); dst_tc->gp_regs[PT_MSR] |= MSR_VEC; } else { put_altivec_regs(&sigframe->uc.uc_mcontext, fpregs->vrregs); } dst->gp_regs[PT_MSR] |= MSR_VEC; if (fpregs->flags & USER_FPREGS_FL_VSX) { if (fpregs->flags & USER_FPREGS_FL_TM) { put_vsx_regs(&sigframe->uc_transact.uc_mcontext, fpregs->tm.vsxregs); put_vsx_regs(&sigframe->uc.uc_mcontext, fpregs->tm.vsxregs); dst_tc->gp_regs[PT_MSR] |= MSR_VSX; } else { put_vsx_regs(&sigframe->uc.uc_mcontext, fpregs->vsxregs); } dst->gp_regs[PT_MSR] |= MSR_VSX; } } return 0; }
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) { int ret = 0; if (CORE_THREAD_ARCH_INFO(core)->fpstate) put_fpu_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->fpstate); if (CORE_THREAD_ARCH_INFO(core)->vrstate) ret = put_altivec_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vrstate); else if (core->ti_ppc64->gpregs->msr & MSR_VEC) { pr_err("Register's data mismatch, corrupted image ?\n"); ret = -1; } if (!ret && CORE_THREAD_ARCH_INFO(core)->vsxstate) ret = put_vsx_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vsxstate); else if (core->ti_ppc64->gpregs->msr & MSR_VSX) { pr_err("VSX register's data mismatch, corrupted image ?\n"); ret = -1; } if (!ret && CORE_THREAD_ARCH_INFO(core)->tmstate) ret = put_tm_regs(sigframe, CORE_THREAD_ARCH_INFO(core)->tmstate); else if (MSR_TM_ACTIVE(core->ti_ppc64->gpregs->msr)) { pr_err("TM register's data mismatch, corrupted image ?\n"); ret = -1; } return ret; }
static int put_tm_regs(struct rt_sigframe *f, UserPpc64TmRegsEntry *tme) { /* * WARNING: As stated in kernel's restore_tm_sigcontexts, TEXASR has to be * restored by the process itself : * TEXASR was set by the signal delivery reclaim, as was TFIAR. * Users doing anything abhorrent like thread-switching w/ signals for * TM-Suspended code will have to back TEXASR/TFIAR up themselves. * For the case of getting a signal and simply returning from it, * we don't need to re-copy them here. */ ucontext_t *tm_uc = &f->uc_transact; pr_debug("Restoring TM registers FP:%d VR:%d VSX:%d\n", !!(tme->fpstate), !!(tme->vrstate), !!(tme->vsxstate)); restore_gp_regs(&tm_uc->uc_mcontext, tme->gpregs); if (tme->fpstate) put_fpu_regs(&tm_uc->uc_mcontext, tme->fpstate); if (tme->vrstate && put_altivec_regs(&tm_uc->uc_mcontext, tme->vrstate)) return -1; if (tme->vsxstate && put_vsx_regs(&tm_uc->uc_mcontext, tme->vsxstate)) return -1; f->uc.uc_link = tm_uc; return 0; }
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) { int ret = 0; if (CORE_THREAD_ARCH_INFO(core)->fpstate) put_fpu_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->fpstate); if (CORE_THREAD_ARCH_INFO(core)->vrstate) ret = put_altivec_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vrstate); else if (core->ti_ppc64->gpregs->msr & MSR_VEC) { pr_err("Internal error\n"); ret = -1; } if (!ret && CORE_THREAD_ARCH_INFO(core)->vsxstate) ret = put_vsx_regs(&sigframe->uc.uc_mcontext, CORE_THREAD_ARCH_INFO(core)->vsxstate); else if (core->ti_ppc64->gpregs->msr & MSR_VSX) { pr_err("Internal error\n"); ret = -1; } return ret; }