Try harder to give new processes a clean initial fpu state. fpu_cleanstate

wasn't actually clean, it was saving the xmm registers as left over by the
bios.  fninit() doesn't clear those.

In fpudna(), instead of doing a fninit() and forgetting to load the initial
mxcsr, do a full fxrstor(&fpu_cleanstate).  Otherwise we hand over whatever
random values are left in the xmm registers by the last user.

I'm not certain of whether this is excessive paranoia or not, but there was
an outright bug in neglecting to set the mxcsr value that caused awk to
SIGFPE in some case.  Especially for Tim Robbins. :-)

i386 probably should do something about the mxcsr setings too.

Found by:  tjr
This commit is contained in:
Peter Wemm 2004-06-18 04:01:54 +00:00
parent 5214cb3f59
commit a5de0db8b5

View File

@ -125,6 +125,8 @@ fpuinit(void)
ldmxcsr(mxcsr);
fxsave(&fpu_cleanstate);
start_emulating();
bzero(fpu_cleanstate.sv_fp, sizeof(fpu_cleanstate.sv_fp));
bzero(fpu_cleanstate.sv_xmm, sizeof(fpu_cleanstate.sv_xmm));
fpu_cleanstate_ready = 1;
intr_restore(savecrit);
}
@ -384,7 +386,6 @@ fpudna()
{
struct pcb *pcb;
register_t s;
u_short control;
if (PCPU_GET(fpcurthread) == curthread) {
printf("fpudna: fpcurthread == curthread %d times\n",
@ -409,13 +410,10 @@ fpudna()
if ((pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
/*
* This is the first time this thread has used the FPU or
* the PCB doesn't contain a clean FPU state. Explicitly
* initialize the FPU and load the default control word.
* This is the first time this thread has used the FPU,
* explicitly load sanitized registers.
*/
fninit();
control = __INITIAL_FPUCW__;
fldcw(&control);
fxrstor(&fpu_cleanstate);
pcb->pcb_flags |= PCB_FPUINITDONE;
} else
fxrstor(&pcb->pcb_save);