ref: 96511b274de06c994597e45236730fee324fd15f
parent: 8b40eecea8905cd70b240df77b0f30814a2adf73
author: cinap_lenrek <[email protected]>
date: Sat May 25 18:44:19 EDT 2013
kernel: fix floating point exceptions (was broken by sse kernel changes) the fpenv() instruction stores in x87 format, using mathstate() would interpret fpsave as FPssestate in case it was enabled! instead, pass the status word and fppc explicitely to mathnote() in matherror(). get rid of m->fpsavealign buffer, as we can just use FPssesave struct which has enougth padding so rounding up base pointer will not overflow.
--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -256,7 +256,6 @@
uvlong tscticks;
int pdballoc;
int pdbfree;
- FPsave *fpsavalign;
vlong mtrrcap;
vlong mtrrdef;
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -480,37 +480,11 @@
};
static void
-mathstate(ulong *stsp, ulong *pcp, ulong *ctlp)
+mathnote(ulong status, ulong pc)
{
- ulong sts, fpc, ctl;
- FPsave *f = &up->fpsave;
-
- if(fpsave == fpx87save){
- sts = f->status;
- fpc = f->pc;
- ctl = f->control;
- } else {
- sts = f->fsw;
- fpc = f->fpuip;
- ctl = f->fcw;
- }
- if(stsp)
- *stsp = sts;
- if(pcp)
- *pcp = fpc;
- if(ctlp)
- *ctlp = ctl;
-}
-
-static void
-mathnote(void)
-{
- int i;
- ulong status, pc;
char *msg, note[ERRMAX];
+ int i;
- mathstate(&status, &pc, nil);
-
/*
* Some attention should probably be paid here to the
* exception masks and error summary.
@@ -532,7 +506,7 @@
msg = "invalid operation";
}
snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux",
- msg, up->fpsave.pc, status);
+ msg, pc, status);
postnote(up, 1, note, NDebug);
}
@@ -540,7 +514,6 @@
* sse fp save and restore buffers have to be 16-byte (FPalign) aligned,
* so we shuffle the data up and down as needed or make copies.
*/
-
void
fpssesave(FPsave *fps)
{
@@ -548,7 +521,7 @@
afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
fpssesave0(afps);
- if (fps != afps) /* not aligned? shuffle down from aligned buffer */
+ if(fps != afps) /* not aligned? shuffle down from aligned buffer */
memmove(fps, afps, sizeof(FPssestate) - FPalign);
}
@@ -558,28 +531,46 @@
FPsave *afps;
afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
- if (fps != afps) {
- if (m->fpsavalign == nil)
- m->fpsavalign = mallocalign(sizeof(FPssestate),
- FPalign, 0, 0);
- if (m->fpsavalign)
- afps = m->fpsavalign;
- /* copy or shuffle up to make aligned */
+ if(fps != afps) /* shuffle up to make aligned */
memmove(afps, fps, sizeof(FPssestate) - FPalign);
- }
fpsserestore0(afps);
- /* if we couldn't make a copy, shuffle regs back down */
- if (fps != afps && afps != m->fpsavalign)
+ if(fps != afps) /* shuffle regs back down when unaligned */
memmove(fps, afps, sizeof(FPssestate) - FPalign);
}
/*
+ * extract control, status and fppc from process
+ * floating point state independent of format.
+ */
+static void
+mathstate(ulong *stsp, ulong *pcp, ulong *ctlp)
+{
+ ulong sts, fpc, ctl;
+ FPsave *f = &up->fpsave;
+
+ if(fpsave == fpx87save){
+ sts = f->status;
+ fpc = f->pc;
+ ctl = f->control;
+ } else {
+ sts = f->fsw;
+ fpc = f->fpuip;
+ ctl = f->fcw;
+ }
+ if(stsp)
+ *stsp = sts;
+ if(pcp)
+ *pcp = fpc;
+ if(ctlp)
+ *ctlp = ctl;
+}
+
+/*
* math coprocessor error
*/
static void
-matherror(Ureg *ur, void*)
+matherror(Ureg*, void*)
{
- ulong status, pc;
/*
* a write cycle to port 0xF0 clears the interrupt latch attached
* to the error# line from the 387
@@ -588,16 +579,10 @@
outb(0xF0, 0xFF);
/*
- * save floating point state to check out error
+ * get floating point state to check out error
*/
fpenv(&up->fpsave);
- mathnote();
-
- if((ur->pc & 0xf0000000) == KZERO){
- mathstate(&status, &pc, nil);
- panic("fp: status %ux fppc=0x%lux pc=0x%lux",
- up->fpsave.status, up->fpsave.pc, ur->pc);
- }
+ mathnote(up->fpsave.status, up->fpsave.pc);
}
/*
@@ -606,7 +591,7 @@
static void
mathemu(Ureg *ureg, void*)
{
- ulong status, control;
+ ulong status, control, pc;
if(up->fpstate & FPillegal){
/* someone did floating point in a note handler */
@@ -626,9 +611,9 @@
* More attention should probably be paid here to the
* exception masks and error summary.
*/
- mathstate(&status, nil, &control);
+ mathstate(&status, &pc, &control);
if((status & ~control) & 0x07F){
- mathnote();
+ mathnote(status, pc);
break;
}
fprestore(&up->fpsave);