Exemple #1
0
static int protected_restore_fp_context(struct sigcontext __user *sc)
{
	int err, tmp __maybe_unused;
#ifndef CONFIG_EVA
	while (1) {
		lock_fpu_owner();
		if (is_fpu_owner()) {
			err = restore_fp_context(sc);
			unlock_fpu_owner();
		} else {
			unlock_fpu_owner();
			err = copy_fp_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.
	 */
	lose_fpu(0);
	err = restore_fp_context(sc); /* this might fail */
#endif
	return err;
}
Exemple #2
0
asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
    int err = 0;

    /* 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);
    err |= __get_user(regs->hi, &sc->sc_mdhi);
    err |= __get_user(regs->lo, &sc->sc_mdlo);

#define restore_gp_reg(i) do {						\
	err |= __get_user(regs->regs[i], &sc->sc_regs[i]);		\
} while(0)
    restore_gp_reg( 1);
    restore_gp_reg( 2);
    restore_gp_reg( 3);
    restore_gp_reg( 4);
    restore_gp_reg( 5);
    restore_gp_reg( 6);
    restore_gp_reg( 7);
    restore_gp_reg( 8);
    restore_gp_reg( 9);
    restore_gp_reg(10);
    restore_gp_reg(11);
    restore_gp_reg(12);
    restore_gp_reg(13);
    restore_gp_reg(14);
    restore_gp_reg(15);
    restore_gp_reg(16);
    restore_gp_reg(17);
    restore_gp_reg(18);
    restore_gp_reg(19);
    restore_gp_reg(20);
    restore_gp_reg(21);
    restore_gp_reg(22);
    restore_gp_reg(23);
    restore_gp_reg(24);
    restore_gp_reg(25);
    restore_gp_reg(26);
    restore_gp_reg(27);
    restore_gp_reg(28);
    restore_gp_reg(29);
    restore_gp_reg(30);
    restore_gp_reg(31);
#undef restore_gp_reg

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

    if (current->used_math) {
        /* restore fpu context if we have used it before */
        own_fpu();
        err |= restore_fp_context(sc);
    } else {
        /* signal handler may have used FPU.  Give it up. */
        lose_fpu();
    }

    return err;
}
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
static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
	int owned_fp;
	int err = 0;
	u64 reg;

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

	err |= __get_user(reg, &sc->sc_mdhi);
	regs->hi = (int) reg;
	err |= __get_user(reg, &sc->sc_mdlo);
	regs->lo = (int) reg;

#define restore_gp_reg(i) do {						\
	err |= __get_user(reg, &sc->sc_regs[i]);			\
	regs->regs[i] = reg;						\
} while(0);
	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
	restore_gp_reg(31);
#undef restore_gp_reg

	err |= __get_user(owned_fp, &sc->sc_ownedfp);
	err |= __get_user(current->used_math, &sc->sc_used_math);

	if (owned_fp) {
		err |= restore_fp_context(sc);
		goto out;
	}

	if (current == last_task_used_math) {
		/* Signal handler acquired FPU - give it back */
		last_task_used_math = NULL;
		regs->cp0_status &= ~ST0_CU1;
	}
	if (current->used_math) {
		/* Undo possible contamination of thread state */
		err |= restore_thread_fp_context(sc);
	}

out:
	return err;
}
Exemple #5
0
static int protected_restore_fp_context(struct sigcontext __user *sc)
{
	int err, tmp __maybe_unused;
	while (1) {
		lock_fpu_owner();
		own_fpu_inatomic(0);
		err = restore_fp_context(sc); /* this might fail */
		unlock_fpu_owner();
		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 #6
0
static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
	int err = 0;
	u64 reg;

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

	err |= __get_user(reg, &sc->sc_mdhi);
	regs->hi = (int) reg;
	err |= __get_user(reg, &sc->sc_mdlo);
	regs->lo = (int) reg;

#define restore_gp_reg(i) do {						\
	err |= __get_user(reg, &sc->sc_regs[i]);			\
	regs->regs[i] = reg;						\
} while(0)
	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
	restore_gp_reg(31);
#undef restore_gp_reg

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

	if (current->used_math) {
		/* restore fpu context if we have used it before */
		own_fpu();
		err |= restore_fp_context(sc);
	} else {
		/* signal handler may have used FPU.  Give it up. */
		lose_fpu();
	}

	return err;
}
Exemple #7
0
asmlinkage int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
	int owned_fp;
	int err = 0;
	u64 reg;

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

	err |= __get_user(reg, &sc->sc_mdhi);
	regs->hi = (int) reg;
	err |= __get_user(reg, &sc->sc_mdlo);
	regs->lo = (int) reg;

#define restore_gp_reg(i) do {						\
	err |= __get_user(reg, &sc->sc_regs[i]);			\
	regs->regs[i] = reg;						\
} while(0);
	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
	restore_gp_reg(31);
#undef restore_gp_reg

	err |= __get_user(owned_fp, &sc->sc_ownedfp);
	if (owned_fp) {
		err |= restore_fp_context(sc);
		last_task_used_math = current;
	}

	return err;
}