in kernel/signal.c [331:424]
static inline int rt_restore_fpu_state(struct ucontext __user *uc)
{
unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0);
fpregset_t fpregs;
int err = 1;
if (FPU_IS_EMU) {
/* restore fpu control register */
if (__copy_from_user(current->thread.fpcntl,
uc->uc_mcontext.fpregs.f_fpcntl, 12))
goto out;
/* restore all other fpu register */
if (__copy_from_user(current->thread.fp,
uc->uc_mcontext.fpregs.f_fpregs, 96))
goto out;
return 0;
}
if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
goto out;
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
context_size = fpstate[1];
/* Verify the frame format. */
if (!(CPU_IS_060 || CPU_IS_COLDFIRE) &&
(fpstate[0] != fpu_version))
goto out;
if (CPU_IS_020_OR_030) {
if (m68k_fputype & FPU_68881 &&
!(context_size == 0x18 || context_size == 0xb4))
goto out;
if (m68k_fputype & FPU_68882 &&
!(context_size == 0x38 || context_size == 0xd4))
goto out;
} else if (CPU_IS_040) {
if (!(context_size == 0x00 ||
context_size == 0x28 ||
context_size == 0x60))
goto out;
} else if (CPU_IS_060) {
if (!(fpstate[3] == 0x00 ||
fpstate[3] == 0x60 ||
fpstate[3] == 0xe0))
goto out;
} else if (CPU_IS_COLDFIRE) {
if (!(fpstate[3] == 0x00 ||
fpstate[3] == 0x05 ||
fpstate[3] == 0xe5))
goto out;
} else
goto out;
if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
sizeof(fpregs)))
goto out;
if (CPU_IS_COLDFIRE) {
__asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t"
"fmovel %1,%%fpcr\n\t"
"fmovel %2,%%fpsr\n\t"
"fmovel %3,%%fpiar"
: /* no outputs */
: "m" (fpregs.f_fpregs[0]),
"m" (fpregs.f_fpcntl[0]),
"m" (fpregs.f_fpcntl[1]),
"m" (fpregs.f_fpcntl[2]));
} else {
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%%fp0-%%fp7\n\t"
"fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
".chip 68k"
: /* no outputs */
: "m" (*fpregs.f_fpregs),
"m" (*fpregs.f_fpcntl));
}
}
if (context_size &&
__copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
context_size))
goto out;
if (CPU_IS_COLDFIRE) {
__asm__ volatile ("frestore %0" : : "m" (*fpstate));
} else {
__asm__ volatile (".chip 68k/68881\n\t"
"frestore %0\n\t"
".chip 68k"
: : "m" (*fpstate));
}
err = 0;
out:
return err;
}