Exemple #1
0
static int protected_restore_fp_context32(struct sigcontext32 __user *sc,
					  unsigned used_math)
{
	int err, tmp __maybe_unused;
	bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
	while (1) {
		lock_fpu_owner();
		if (is_fpu_owner()) {
			err = restore_fp_context32(sc);
			if (restore_msa && !err) {
				enable_msa();
				err = _restore_msa_context32(sc);
			} else {
				/* signal handler may have used MSA */
				disable_msa();
			}
			unlock_fpu_owner();
		} else {
			unlock_fpu_owner();
			err = copy_fp_from_sigcontext32(sc);
			if (restore_msa && !err)
				err = copy_msa_from_sigcontext32(sc);
		}
		if (likely(!err))
			break;
		/* touch the sigcontext and try again */
		err = __get_user(tmp, &sc->sc_fpregs[0]) |
			__get_user(tmp, &sc->sc_fpregs[31]) |
			__get_user(tmp, &sc->sc_fpc_csr);
		if (err)
			break;	/* really bad sigcontext */
	}
	return err;
}
Exemple #2
0
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
	unsigned long status;

	/* New thread loses kernel privileges. */
	status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
	status |= KU_USER;
	regs->cp0_status = status;
	clear_used_math();
	clear_fpu_owner();
	init_dsp();
	clear_thread_flag(TIF_USEDMSA);
	clear_thread_flag(TIF_MSA_CTX_LIVE);
	disable_msa();
	regs->cp0_epc = pc;
	regs->regs[29] = sp;
}
Exemple #3
0
static int protected_restore_fp_context(struct sigcontext __user *sc,
					unsigned used_math)
{
	int err, tmp __maybe_unused;
	bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
#ifndef CONFIG_EVA
	while (1) {
		lock_fpu_owner();
		if (is_fpu_owner()) {
			err = restore_fp_context(sc);
			if (restore_msa && !err) {
				enable_msa();
				err = _restore_msa_context(sc);
			} else {
				/* signal handler may have used MSA */
				disable_msa();
			}
			unlock_fpu_owner();
		} else {
			unlock_fpu_owner();
			err = copy_fp_from_sigcontext(sc);
			if (!err && (used_math & USEDMATH_MSA))
				err = copy_msa_from_sigcontext(sc);
		}
		if (likely(!err))
			break;
		/* touch the sigcontext and try again */
		err = __get_user(tmp, &sc->sc_fpregs[0]) |
			__get_user(tmp, &sc->sc_fpregs[31]) |
			__get_user(tmp, &sc->sc_fpc_csr);
		if (err)
			break;	/* really bad sigcontext */
	}
#else
	/*
	 * EVA does not have FPU EVA instructions so restoring fpu context
	 * directly does not work.
	 */
	enable_msa();
	lose_fpu(0);
	err = restore_fp_context(sc); /* this might fail */
	if (restore_msa && !err)
		err = copy_msa_from_sigcontext(sc);
#endif
	return err;
}
Exemple #4
0
int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
	unsigned int used_math;
	unsigned long treg;
	int err = 0;
	int i;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	err |= __get_user(regs->cp0_epc, &sc->sc_pc);

#ifdef CONFIG_CPU_HAS_SMARTMIPS
	err |= __get_user(regs->acx, &sc->sc_acx);
#endif
	err |= __get_user(regs->hi, &sc->sc_mdhi);
	err |= __get_user(regs->lo, &sc->sc_mdlo);
	if (cpu_has_dsp) {
		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
	}

	for (i = 1; i < 32; i++)
		err |= __get_user(regs->regs[i], &sc->sc_regs[i]);

	err |= __get_user(used_math, &sc->sc_used_math);
	conditional_used_math(used_math);

	if (used_math) {
		/* restore fpu context if we have used it before */
		if (!err)
			err = check_and_restore_fp_context(sc, used_math);
	} else {
		/* signal handler may have used FPU or MSA. Disable them. */
		disable_msa();
		lose_fpu(0);
	}

	return err;
}
Exemple #5
0
/*
 * Helper routines
 */
static int protected_save_fp_context(struct sigcontext __user *sc,
				     unsigned used_math)
{
	int err;
	bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
#ifndef CONFIG_EVA
	while (1) {
		lock_fpu_owner();
		if (is_fpu_owner()) {
			err = save_fp_context(sc);
			if (save_msa && !err)
				err = _save_msa_context(sc);
			unlock_fpu_owner();
		} else {
			unlock_fpu_owner();
			err = copy_fp_to_sigcontext(sc);
			if (save_msa && !err)
				err = copy_msa_to_sigcontext(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 */
	}
#else
	/*
	 * EVA does not have FPU EVA instructions so saving fpu context directly
	 * does not work.
	 */
	disable_msa();
	lose_fpu(1);
	err = save_fp_context(sc); /* this might fail */
	if (save_msa && !err)
		err = copy_msa_to_sigcontext(sc);
#endif
	return err;
}