/* * sigcontext handlers */ static int protected_save_fp_context32(struct sigcontext32 __user *sc, unsigned used_math) { int err; bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA); while (1) { lock_fpu_owner(); if (is_fpu_owner()) { err = save_fp_context32(sc); if (save_msa && !err) err = _save_msa_context32(sc); unlock_fpu_owner(); } else { unlock_fpu_owner(); err = copy_fp_to_sigcontext32(sc); if (save_msa && !err) err = copy_msa_to_sigcontext32(sc); } if (likely(!err)) break; /* touch the sigcontext and try again */ err = __put_user(0, &sc->sc_fpregs[0]) | __put_user(0, &sc->sc_fpregs[31]) | __put_user(0, &sc->sc_fpc_csr); if (err) break; /* really bad sigcontext */ } return err; }
static inline int setup_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc) { int err = 0; err |= __put_user(regs->cp0_epc, &sc->sc_pc); err |= __put_user(regs->cp0_status, &sc->sc_status); #define save_gp_reg(i) { \ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ } while(0) __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18); save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22); save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30); save_gp_reg(31); #undef save_gp_reg err |= __put_user(regs->hi, &sc->sc_mdhi); err |= __put_user(regs->lo, &sc->sc_mdlo); if (cpu_has_dsp) { err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); err |= __put_user(mfhi1(), &sc->sc_hi1); err |= __put_user(mflo1(), &sc->sc_lo1); err |= __put_user(mfhi2(), &sc->sc_hi2); err |= __put_user(mflo2(), &sc->sc_lo2); err |= __put_user(mfhi3(), &sc->sc_hi3); err |= __put_user(mflo3(), &sc->sc_lo3); } err |= __put_user(!!used_math(), &sc->sc_used_math); if (!used_math()) goto out; /* * Save FPU state to signal context. Signal handler will "inherit" * current FPU state. */ preempt_disable(); if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } err |= save_fp_context32(sc); preempt_enable(); out: return err; }
/* * sigcontext handlers */ static int protected_save_fp_context32(struct sigcontext32 __user *sc) { int err; while (1) { lock_fpu_owner(); own_fpu_inatomic(1); err = save_fp_context32(sc); /* this might fail */ unlock_fpu_owner(); if (likely(!err)) break; /* touch the sigcontext and try again */ err = __put_user(0, &sc->sc_fpregs[0]) | __put_user(0, &sc->sc_fpregs[31]) | __put_user(0, &sc->sc_fpc_csr); if (err) break; /* really bad sigcontext */ } return err; }
/* * sigcontext handlers */ static int protected_save_fp_context32(struct sigcontext32 __user *sc) { int err; while (1) { lock_fpu_owner(); if (is_fpu_owner()) { err = save_fp_context32(sc); unlock_fpu_owner(); } else { unlock_fpu_owner(); err = copy_fp_to_sigcontext32(sc); } if (likely(!err)) break; /* touch the sigcontext and try again */ err = __put_user(0, &sc->sc_fpregs[0]) | __put_user(0, &sc->sc_fpregs[31]) | __put_user(0, &sc->sc_fpc_csr); if (err) break; /* really bad sigcontext */ } return err; }