|
@@ -701,6 +701,13 @@ asmlinkage void do_ov(struct pt_regs *regs)
|
|
|
|
|
|
int process_fpemu_return(int sig, void __user *fault_addr)
|
|
int process_fpemu_return(int sig, void __user *fault_addr)
|
|
{
|
|
{
|
|
|
|
+ /*
|
|
|
|
+ * We can't allow the emulated instruction to leave any of the cause
|
|
|
|
+ * bits set in FCSR. If they were then the kernel would take an FP
|
|
|
|
+ * exception when restoring FP context.
|
|
|
|
+ */
|
|
|
|
+ current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
|
|
|
|
+
|
|
if (sig == SIGSEGV || sig == SIGBUS) {
|
|
if (sig == SIGSEGV || sig == SIGBUS) {
|
|
struct siginfo si = {0};
|
|
struct siginfo si = {0};
|
|
si.si_addr = fault_addr;
|
|
si.si_addr = fault_addr;
|
|
@@ -804,18 +811,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
|
|
sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
|
|
sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
|
|
&fault_addr);
|
|
&fault_addr);
|
|
|
|
|
|
- /*
|
|
|
|
- * We can't allow the emulated instruction to leave any of
|
|
|
|
- * the cause bit set in $fcr31.
|
|
|
|
- */
|
|
|
|
- current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
|
|
|
|
|
|
+ /* If something went wrong, signal */
|
|
|
|
+ process_fpemu_return(sig, fault_addr);
|
|
|
|
|
|
/* Restore the hardware register state */
|
|
/* Restore the hardware register state */
|
|
own_fpu(1); /* Using the FPU again. */
|
|
own_fpu(1); /* Using the FPU again. */
|
|
|
|
|
|
- /* If something went wrong, signal */
|
|
|
|
- process_fpemu_return(sig, fault_addr);
|
|
|
|
-
|
|
|
|
goto out;
|
|
goto out;
|
|
} else if (fcr31 & FPU_CSR_INV_X)
|
|
} else if (fcr31 & FPU_CSR_INV_X)
|
|
info.si_code = FPE_FLTINV;
|
|
info.si_code = FPE_FLTINV;
|