kernel: introduce per process FPU struct (PFPU) for more flexible machine specific fpu handling

introducing the PFPU structue which allows the machine specific
code some flexibility on how to handle the FPU process state.

for example, in the pc and pc64 kernel, the FPsave structure is
arround 512 bytes. with avx512, it could grow up to 2K. instead
of embedding that into the Proc strucutre, it is more effective
to allocate it on first use of the fpu, as most processes do not
use simd or floating point in the first place. also, the FPsave
structure has special 16 byte alignment constraint, which further
favours dynamic allocation.

this gets rid of the memmoves in pc/pc64 kernels for the aligment.

there is also devproc, which is now checking if the fpsave area
is actually valid before reading it, avoiding debuggers to see
garbage data.

the Notsave structure is gone now, as it was not used on any
machine.
This commit is contained in:
cinap_lenrek 2017-11-04 20:08:22 +01:00
parent 04ce485f1b
commit 24057fd4f4
35 changed files with 258 additions and 344 deletions

View file

@ -15,13 +15,13 @@ enum {
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct Memcache Memcache; typedef struct Memcache Memcache;
typedef struct MMMU MMMU; typedef struct MMMU MMMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct Page Page; typedef struct Page Page;
typedef struct PhysUart PhysUart; typedef struct PhysUart PhysUart;
typedef struct PMMU PMMU; typedef struct PMMU PMMU;
@ -56,14 +56,14 @@ struct Label
uintptr pc; uintptr pc;
}; };
/*
* emulated or vfp3 floating point
*/
enum { enum {
Maxfpregs = 32, /* could be 16 or 32, see Mach.fpnregs */ Maxfpregs = 32, /* could be 16 or 32, see Mach.fpnregs */
Nfpctlregs = 16, Nfpctlregs = 16,
}; };
/*
* emulated or vfp3 floating point
*/
struct FPsave struct FPsave
{ {
ulong status; ulong status;
@ -78,9 +78,12 @@ struct FPsave
uintptr pc; /* of failed fp instr. */ uintptr pc; /* of failed fp instr. */
}; };
/* struct PFPU
* FPsave.fpstate {
*/ int fpstate;
FPsave fpsave[1];
};
enum enum
{ {
FPinit, FPinit,
@ -119,13 +122,6 @@ struct Conf
int monitor; /* flag */ int monitor; /* flag */
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave {
int emptiness;
};
/* /*
* MMU stuff in Mach. * MMU stuff in Mach.
*/ */

View file

@ -650,7 +650,7 @@ fpiarm(Ureg *ur)
if(up == nil) if(up == nil)
panic("fpiarm not in a process"); panic("fpiarm not in a process");
ufp = &up->fpsave; ufp = up->fpsave;
/* /*
* because all the emulated fp state is in the proc structure, * because all the emulated fp state is in the proc structure,
* it need not be saved/restored * it need not be saved/restored

View file

@ -222,7 +222,7 @@ void
fpunotify(Ureg*) fpunotify(Ureg*)
{ {
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;
@ -259,11 +259,11 @@ fprestore(Proc *p)
int n; int n;
fpon(); fpon();
fpwr(Fpscr, p->fpsave.control); fpwr(Fpscr, p->fpsave->control);
m->fpscr = fprd(Fpscr) & ~Allcc; m->fpscr = fprd(Fpscr) & ~Allcc;
assert(m->fpnregs); assert(m->fpnregs);
for (n = 0; n < m->fpnregs; n++) for (n = 0; n < m->fpnregs; n++)
fprestreg(n, *(uvlong *)p->fpsave.regs[n]); fprestreg(n, *(uvlong *)p->fpsave->regs[n]);
} }
/* /*
@ -288,7 +288,7 @@ fpuprocsave(Proc *p)
* until the process runs again and generates an * until the process runs again and generates an
* emulation fault to activate the FPU. * emulation fault to activate the FPU.
*/ */
fpsave(&p->fpsave); fpsave(p->fpsave);
} }
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
@ -317,11 +317,11 @@ fpuprocfork(Proc *p)
s = splhi(); s = splhi();
switch(up->fpstate & ~FPillegal){ switch(up->fpstate & ~FPillegal){
case FPactive: case FPactive:
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
/* no break */ /* no break */
case FPinactive: case FPinactive:
p->fpsave = up->fpsave; memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
splx(s); splx(s);
@ -345,7 +345,7 @@ mathnote(void)
ulong status; ulong status;
char *msg, note[ERRMAX]; char *msg, note[ERRMAX];
status = up->fpsave.status; status = up->fpsave->status;
/* /*
* Some attention should probably be paid here to the * Some attention should probably be paid here to the
@ -364,7 +364,7 @@ mathnote(void)
else else
msg = "spurious"; msg = "spurious";
snprint(note, sizeof note, "sys: fp: %s fppc=%#p status=%#lux", snprint(note, sizeof note, "sys: fp: %s fppc=%#p status=%#lux",
msg, up->fpsave.pc, status); msg, up->fpsave->pc, status);
postnote(up, 1, note, NDebug); postnote(up, 1, note, NDebug);
} }
@ -388,7 +388,7 @@ mathemu(Ureg *)
* More attention should probably be paid here to the * More attention should probably be paid here to the
* exception masks and error summary. * exception masks and error summary.
*/ */
if(up->fpsave.status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){ if(up->fpsave->status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){
mathnote(); mathnote();
break; break;
} }

View file

@ -1,13 +1,13 @@
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct Memcache Memcache; typedef struct Memcache Memcache;
typedef struct MMMU MMMU; typedef struct MMMU MMMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct Page Page; typedef struct Page Page;
typedef struct Pcidev Pcidev; typedef struct Pcidev Pcidev;
typedef struct PhysUart PhysUart; typedef struct PhysUart PhysUart;
@ -45,13 +45,13 @@ struct Label
uintptr pc; uintptr pc;
}; };
/*
* emulated floating point
*/
enum{ enum{
Nfpctlregs = 16, Nfpctlregs = 16,
}; };
/*
* emulated floating point
*/
struct FPsave struct FPsave
{ {
ulong status; ulong status;
@ -61,9 +61,12 @@ struct FPsave
int fpstate; int fpstate;
}; };
/* struct PFPU
* FPsave.status {
*/ int fpstate;
FPsave fpsave[1];
};
enum enum
{ {
FPinit, FPinit,
@ -98,13 +101,6 @@ struct Conf
// ulong mhz; // ulong mhz;
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave {
int emptiness;
};
/* /*
* MMU stuff in Mach. * MMU stuff in Mach.
*/ */

View file

@ -726,7 +726,7 @@ fpiarm(Ureg *ur)
if(up == nil) if(up == nil)
panic("fpiarm not in a process"); panic("fpiarm not in a process");
ufp = &up->fpsave; ufp = up->fpsave;
/* /*
* because all the emulated fp state is in the proc structure, * because all the emulated fp state is in the proc structure,
* it need not be saved/restored * it need not be saved/restored

View file

@ -1,11 +1,11 @@
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct Page Page; typedef struct Page Page;
typedef struct PCArch PCArch; typedef struct PCArch PCArch;
typedef struct Pcidev Pcidev; typedef struct Pcidev Pcidev;
@ -45,16 +45,6 @@ struct Label
ulong pc; ulong pc;
}; };
/*
* Proc.fpstate
*/
enum
{
FPinit,
FPactive,
FPinactive,
};
/* /*
* This structure must agree with fpsave and fprestore asm routines * This structure must agree with fpsave and fprestore asm routines
*/ */
@ -70,6 +60,19 @@ struct FPsave
}; };
}; };
struct PFPU
{
int fpstate;
FPsave fpsave[1];
};
enum
{
FPinit,
FPactive,
FPinactive,
};
struct Confmem struct Confmem
{ {
ulong base; ulong base;
@ -103,14 +106,6 @@ struct PMMU
int mmupid; int mmupid;
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave
{
ulong UNUSED;
};
#include "../port/portdat.h" #include "../port/portdat.h"
/* /*

View file

@ -241,7 +241,7 @@ procsave(Proc *p)
{ {
if(p->fpstate == FPactive){ if(p->fpstate == FPactive){
if(p->state != Moribund) if(p->state != Moribund)
fpsave(&up->fpsave); fpsave(up->fpsave);
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
} }

View file

@ -246,7 +246,7 @@ trap(Ureg *ureg)
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPinactive: case FPinactive:
fprestore(&up->fpsave); fprestore(up->fpsave);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
default: default:

View file

@ -27,6 +27,7 @@ enum {
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
@ -34,7 +35,6 @@ typedef struct Memcache Memcache;
typedef struct MMMU MMMU; typedef struct MMMU MMMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef u32int Mreg; /* Msr - bloody UART */ typedef u32int Mreg; /* Msr - bloody UART */
typedef struct Notsave Notsave;
typedef struct Page Page; typedef struct Page Page;
typedef struct PhysUart PhysUart; typedef struct PhysUart PhysUart;
typedef struct PMMU PMMU; typedef struct PMMU PMMU;
@ -69,13 +69,13 @@ struct Label
uintptr pc; uintptr pc;
}; };
/*
* emulated floating point
*/
enum{ enum{
Nfpctlregs = 16, Nfpctlregs = 16,
}; };
/*
* emulated floating point
*/
struct FPsave struct FPsave
{ {
ulong status; ulong status;
@ -85,9 +85,12 @@ struct FPsave
int fpstate; int fpstate;
}; };
/* struct PFPU
* FPsave.status {
*/ int fpstate;
FPsave fpsave[1];
};
enum enum
{ {
FPinit, FPinit,
@ -122,13 +125,6 @@ struct Conf
int monitor; /* flag */ int monitor; /* flag */
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave {
int emptiness;
};
/* /*
* MMU stuff in Mach. * MMU stuff in Mach.
*/ */

View file

@ -726,7 +726,7 @@ fpiarm(Ureg *ur)
if(up == nil) if(up == nil)
panic("fpiarm not in a process"); panic("fpiarm not in a process");
ufp = &up->fpsave; ufp = up->fpsave;
/* /*
* because all the emulated fp state is in the proc structure, * because all the emulated fp state is in the proc structure,
* it need not be saved/restored * it need not be saved/restored

View file

@ -3,14 +3,14 @@ typedef struct BIOS32ci BIOS32ci;
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef union FPsave FPsave; typedef union FPsave FPsave;
typedef struct FPx87state FPx87state;
typedef struct FPssestate FPssestate; typedef struct FPssestate FPssestate;
typedef struct FPstate FPstate; typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct MMU MMU; typedef struct MMU MMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct PCArch PCArch; typedef struct PCArch PCArch;
typedef struct Pcidev Pcidev; typedef struct Pcidev Pcidev;
typedef struct PCMmap PCMmap; typedef struct PCMmap PCMmap;
@ -51,22 +51,7 @@ struct Label
ulong pc; ulong pc;
}; };
struct FPx87state /* x87 fp state */
/*
* FPsave.status
*/
enum
{
/* this is a state */
FPinit= 0,
FPactive= 1,
FPinactive= 2,
/* the following is a bit that can be or'd into the state */
FPillegal= 0x100,
};
struct FPstate
{ {
ushort control; ushort control;
ushort r1; ushort r1;
@ -98,18 +83,30 @@ struct FPssestate /* SSE fp state */
ulong mxcsr; /* MXCSR register state */ ulong mxcsr; /* MXCSR register state */
ulong mxcsr_mask; /* MXCSR mask register */ ulong mxcsr_mask; /* MXCSR mask register */
uchar xregs[480]; /* extended registers */ uchar xregs[480]; /* extended registers */
uchar alignpad[FPalign];
}; };
/*
* the FP regs must be stored here, not somewhere pointed to from here.
* port code assumes this.
*/
union FPsave { union FPsave {
FPstate; FPx87state;
FPssestate; FPssestate;
}; };
struct PFPU
{
int fpstate;
FPsave *fpsave;
};
enum
{
/* this is a state */
FPinit= 0,
FPactive= 1,
FPinactive= 2,
/* the following is a bit that can be or'd into the state */
FPillegal= 0x100,
};
struct Confmem struct Confmem
{ {
ulong base; ulong base;
@ -164,16 +161,6 @@ struct PMMU
void *vmx; void *vmx;
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave
{
ulong svflags;
ulong svcs;
ulong svss;
};
#include "../port/portdat.h" #include "../port/portdat.h"
typedef struct { typedef struct {

View file

@ -40,9 +40,7 @@ void fpoff(void);
void (*fprestore)(FPsave*); void (*fprestore)(FPsave*);
void (*fpsave)(FPsave*); void (*fpsave)(FPsave*);
void fpsserestore(FPsave*); void fpsserestore(FPsave*);
void fpsserestore0(FPsave*);
void fpssesave(FPsave*); void fpssesave(FPsave*);
void fpssesave0(FPsave*);
void fpx87restore(FPsave*); void fpx87restore(FPsave*);
void fpx87restore0(FPsave*); void fpx87restore0(FPsave*);
void fpx87save(FPsave*); void fpx87save(FPsave*);

View file

@ -622,13 +622,13 @@ TEXT fpclear(SB), $0 /* clear pending exceptions */
FPOFF FPOFF
RET RET
TEXT fpssesave0(SB), $0 /* save state and disable */ TEXT fpssesave(SB), $0 /* save state and disable */
MOVL p+0(FP), AX MOVL p+0(FP), AX
FXSAVE 0(AX) /* no WAIT */ FXSAVE 0(AX) /* no WAIT */
FPOFF FPOFF
RET RET
TEXT fpsserestore0(SB), $0 /* enable and restore state */ TEXT fpsserestore(SB), $0 /* enable and restore state */
FPON FPON
MOVL p+0(FP), AX MOVL p+0(FP), AX
FXRSTOR 0(AX) FXRSTOR 0(AX)

View file

@ -311,12 +311,8 @@ confinit(void)
} }
/* /*
* we keep FPsave structure in sse format emulating FXSAVE / FXRSTOR * we keep FPsave structure in SSE format emulating FXSAVE / FXRSTOR
* instructions for legacy x87 fpu. * instructions for legacy x87 fpu.
*
* Note that fpx87restore() and fpxsserestore() do modify the FPsave
* data structure for conversion / realignment shuffeling. this means
* that p->fpsave is only valid when p->fpstate == FPinactive.
*/ */
void void
fpx87save(FPsave *fps) fpx87save(FPsave *fps)
@ -441,32 +437,6 @@ fpx87restore(FPsave *fps)
fpx87restore0(fps); fpx87restore0(fps);
} }
/*
* 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)
{
FPsave *afps;
afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
fpssesave0(afps);
if(fps != afps) /* not aligned? shuffle down from aligned buffer */
memmove(fps, afps, sizeof(FPssestate) - FPalign);
}
void
fpsserestore(FPsave *fps)
{
FPsave *afps;
afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
if(fps != afps) /* shuffle up to make aligned */
memmove(afps, fps, sizeof(FPssestate) - FPalign);
fpsserestore0(afps);
}
static char* mathmsg[] = static char* mathmsg[] =
{ {
nil, /* handled below */ nil, /* handled below */
@ -524,9 +494,9 @@ matherror(Ureg*, void*)
/* /*
* get floating point state to check out error * get floating point state to check out error
*/ */
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
mathnote(up->fpsave.fsw, up->fpsave.fpuip); mathnote(up->fpsave->fsw, up->fpsave->fpuip);
} }
/* /*
@ -535,9 +505,9 @@ matherror(Ureg*, void*)
static void static void
simderror(Ureg *ureg, void*) simderror(Ureg *ureg, void*)
{ {
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
mathnote(up->fpsave.mxcsr & 0x3f, ureg->pc); mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc);
} }
/* /*
@ -558,6 +528,8 @@ mathemu(Ureg *ureg, void*)
fpinit(); fpinit();
if(fpsave == fpssesave) if(fpsave == fpssesave)
ldmxcsr(0); /* no simd exceptions on 386 */ ldmxcsr(0); /* no simd exceptions on 386 */
while(up->fpsave == nil)
up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPinactive: case FPinactive:
@ -568,13 +540,13 @@ mathemu(Ureg *ureg, void*)
* More attention should probably be paid here to the * More attention should probably be paid here to the
* exception masks and error summary. * exception masks and error summary.
*/ */
status = up->fpsave.fsw; status = up->fpsave->fsw;
control = up->fpsave.fcw; control = up->fpsave->fcw;
if((status & ~control) & 0x07F){ if((status & ~control) & 0x07F){
mathnote(status, up->fpsave.fpuip); mathnote(status, up->fpsave->fpuip);
break; break;
} }
fprestore(&up->fpsave); fprestore(up->fpsave);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPactive: case FPactive:
@ -645,10 +617,12 @@ procfork(Proc *p)
s = splhi(); s = splhi();
switch(up->fpstate & ~FPillegal){ switch(up->fpstate & ~FPillegal){
case FPactive: case FPactive:
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
case FPinactive: case FPinactive:
p->fpsave = up->fpsave; while(p->fpsave == nil)
p->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
@ -708,7 +682,7 @@ procsave(Proc *p)
* until the process runs again and generates an * until the process runs again and generates an
* emulation fault to activate the FPU. * emulation fault to activate the FPU.
*/ */
fpsave(&p->fpsave); fpsave(p->fpsave);
} }
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }

View file

@ -854,7 +854,7 @@ notify(Ureg* ureg)
return 0; return 0;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;

View file

@ -2,15 +2,13 @@ typedef struct BIOS32si BIOS32si;
typedef struct BIOS32ci BIOS32ci; typedef struct BIOS32ci BIOS32ci;
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef union FPsave FPsave; typedef struct FPsave FPsave;
typedef struct Fxsave Fxsave; typedef struct PFPU PFPU;
typedef struct FPstate FPstate;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct MMU MMU; typedef struct MMU MMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct PCArch PCArch; typedef struct PCArch PCArch;
typedef struct Pcidev Pcidev; typedef struct Pcidev Pcidev;
typedef struct PCMmap PCMmap; typedef struct PCMmap PCMmap;
@ -51,25 +49,8 @@ struct Label
uintptr pc; uintptr pc;
}; };
/* struct FPsave
* FPsave.status
*/
enum
{ {
/* this is a state */
FPinit= 0,
FPactive= 1,
FPinactive= 2,
/* the following is a bit that can be or'd into the state */
FPillegal= 0x100,
};
/*
* the FP regs must be stored here, not somewhere pointed to from here.
* port code assumes this.
*/
struct Fxsave {
u16int fcw; /* x87 control word */ u16int fcw; /* x87 control word */
u16int fsw; /* x87 status word */ u16int fsw; /* x87 status word */
u8int ftw; /* x87 tag word */ u8int ftw; /* x87 tag word */
@ -84,9 +65,21 @@ struct Fxsave {
uchar ign[96]; /* reserved, ignored */ uchar ign[96]; /* reserved, ignored */
}; };
union FPsave { struct PFPU
uchar align[512+15]; {
Fxsave; int fpstate;
FPsave *fpsave;
};
enum
{
/* this is a state */
FPinit= 0,
FPactive= 1,
FPinactive= 2,
/* the following is a bit that can be or'd into the state */
FPillegal= 0x100,
}; };
struct Confmem struct Confmem
@ -149,16 +142,6 @@ struct PMMU
void *vmx; void *vmx;
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave
{
ulong svflags;
ulong svcs;
ulong svss;
};
#include "../port/portdat.h" #include "../port/portdat.h"
typedef struct { typedef struct {

View file

@ -392,15 +392,13 @@ reboot(void *entry, void *code, ulong size)
* SIMD Floating Point. * SIMD Floating Point.
* Assembler support to get at the individual instructions * Assembler support to get at the individual instructions
* is in l.s. * is in l.s.
* There are opportunities to be lazier about saving and
* restoring the state and allocating the storage needed.
*/ */
extern void _clts(void); extern void _clts(void);
extern void _fldcw(u16int); extern void _fldcw(u16int);
extern void _fnclex(void); extern void _fnclex(void);
extern void _fninit(void); extern void _fninit(void);
extern void _fxrstor(Fxsave*); extern void _fxrstor(void*);
extern void _fxsave(Fxsave*); extern void _fxsave(void*);
extern void _fwait(void); extern void _fwait(void);
extern void _ldmxcsr(u32int); extern void _ldmxcsr(u32int);
extern void _stts(void); extern void _stts(void);
@ -418,24 +416,16 @@ fpx87restore(FPsave*)
} }
void void
fpssesave(FPsave *fps) fpssesave(FPsave *s)
{ {
Fxsave *fx = (Fxsave*)ROUND(((uintptr)fps), FPalign); _fxsave(s);
_fxsave(fx);
_stts(); _stts();
if(fx != (Fxsave*)fps)
memmove((Fxsave*)fps, fx, sizeof(Fxsave));
} }
void void
fpsserestore(FPsave *fps) fpsserestore(FPsave *s)
{ {
Fxsave *fx = (Fxsave*)ROUND(((uintptr)fps), FPalign);
if(fx != (Fxsave*)fps)
memmove(fx, (Fxsave*)fps, sizeof(Fxsave));
_clts(); _clts();
_fxrstor(fx); _fxrstor(s);
} }
static char* mathmsg[] = static char* mathmsg[] =
@ -488,9 +478,9 @@ matherror(Ureg*, void*)
/* /*
* Save FPU state to check out the error. * Save FPU state to check out the error.
*/ */
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
mathnote(up->fpsave.fsw, up->fpsave.rip); mathnote(up->fpsave->fsw, up->fpsave->rip);
} }
/* /*
@ -499,9 +489,9 @@ matherror(Ureg*, void*)
static void static void
simderror(Ureg *ureg, void*) simderror(Ureg *ureg, void*)
{ {
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
mathnote(up->fpsave.mxcsr & 0x3f, ureg->pc); mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc);
} }
void void
@ -538,6 +528,8 @@ mathemu(Ureg *ureg, void*)
switch(up->fpstate){ switch(up->fpstate){
case FPinit: case FPinit:
fpinit(); fpinit();
while(up->fpsave == nil)
up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPinactive: case FPinactive:
@ -548,13 +540,13 @@ mathemu(Ureg *ureg, void*)
* More attention should probably be paid here to the * More attention should probably be paid here to the
* exception masks and error summary. * exception masks and error summary.
*/ */
status = up->fpsave.fsw; status = up->fpsave->fsw;
control = up->fpsave.fcw; control = up->fpsave->fcw;
if((status & ~control) & 0x07F){ if((status & ~control) & 0x07F){
mathnote(status, up->fpsave.rip); mathnote(status, up->fpsave->rip);
break; break;
} }
fprestore(&up->fpsave); fprestore(up->fpsave);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPactive: case FPactive:
@ -605,10 +597,12 @@ procfork(Proc *p)
s = splhi(); s = splhi();
switch(up->fpstate & ~FPillegal){ switch(up->fpstate & ~FPillegal){
case FPactive: case FPactive:
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
case FPinactive: case FPinactive:
p->fpsave = up->fpsave; while(p->fpsave == nil)
p->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
splx(s); splx(s);
@ -665,7 +659,7 @@ procsave(Proc *p)
* until the process runs again and generates an * until the process runs again and generates an
* emulation fault to activate the FPU. * emulation fault to activate the FPU.
*/ */
fpsave(&p->fpsave); fpsave(p->fpsave);
} }
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }

View file

@ -823,7 +823,7 @@ notify(Ureg* ureg)
return 0; return 0;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;

View file

@ -1012,7 +1012,9 @@ procread(Chan *c, void *va, long n, vlong off)
goto regread; goto regread;
case Qfpregs: case Qfpregs:
rptr = (uchar*)&p->fpsave; if(p->fpstate != FPinactive)
error(Enoreg);
rptr = (uchar*)p->fpsave;
rsize = sizeof(FPsave); rsize = sizeof(FPsave);
regread: regread:
if(rptr == nil) if(rptr == nil)
@ -1232,7 +1234,9 @@ procwrite(Chan *c, void *va, long n, vlong off)
n = 0; n = 0;
else if(offset+n > sizeof(FPsave)) else if(offset+n > sizeof(FPsave))
n = sizeof(FPsave) - offset; n = sizeof(FPsave) - offset;
memmove((uchar*)&p->fpsave+offset, va, n); if(p->fpstate != FPinactive || p->fpsave == nil)
error(Enoreg);
memmove((uchar*)p->fpsave+offset, va, n);
break; break;
case Qctl: case Qctl:

View file

@ -676,6 +676,8 @@ struct Proc
Fgrp *closingfgrp; /* used during teardown */ Fgrp *closingfgrp; /* used during teardown */
ulong parentpid; ulong parentpid;
int insyscall;
ulong time[6]; /* User, Sys, Real; child U, S, R */ ulong time[6]; /* User, Sys, Real; child U, S, R */
uvlong kentry; /* Kernel entry time stamp (for profiling) */ uvlong kentry; /* Kernel entry time stamp (for profiling) */
@ -689,9 +691,6 @@ struct Proc
*/ */
vlong pcycles; vlong pcycles;
int insyscall;
int fpstate;
QLock debug; /* to access debugging elements of User */ QLock debug; /* to access debugging elements of User */
Proc *pdbg; /* the debugging process */ Proc *pdbg; /* the debugging process */
ulong procmode; /* proc device default file mode */ ulong procmode; /* proc device default file mode */
@ -720,9 +719,8 @@ struct Proc
void (*kpfun)(void*); void (*kpfun)(void*);
void *kparg; void *kparg;
FPsave fpsave; /* address of this is known by db */ int scallnr; /* sys call number */
int scallnr; /* sys call number - known by db */ Sargs s; /* syscall arguments */
Sargs s; /* address of this is known by db */
int nerrlab; int nerrlab;
Label errlab[NERR]; Label errlab[NERR];
char *syserrstr; /* last error from a system call, errbuf0 or 1 */ char *syserrstr; /* last error from a system call, errbuf0 or 1 */
@ -766,17 +764,14 @@ struct Proc
void *ureg; /* User registers for notes */ void *ureg; /* User registers for notes */
void *dbgreg; /* User registers for devproc */ void *dbgreg; /* User registers for devproc */
Notsave;
/* PFPU; /* machine specific fpu state */
* machine specific MMU PMMU; /* machine specific mmu state */
*/
PMMU;
char *syscalltrace; /* syscall trace */ char *syscalltrace; /* syscall trace */
Watchpt *watchpt; /* watchpoints */ Watchpt *watchpt; /* watchpoints */
int nwatchpt; int nwatchpt;
}; };
enum enum

View file

@ -1,11 +1,12 @@
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Imap Imap; typedef struct Imap Imap;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct PCArch PCArch; typedef struct PCArch PCArch;
typedef struct PMMU PMMU; typedef struct PMMU PMMU;
typedef struct Page Page; typedef struct Page Page;
@ -14,6 +15,7 @@ typedef struct Proc Proc;
typedef struct Sys Sys; typedef struct Sys Sys;
typedef struct Ureg Ureg; typedef struct Ureg Ureg;
typedef struct Vctl Vctl; typedef struct Vctl Vctl;
typedef long Tval;
#pragma incomplete Ureg #pragma incomplete Ureg
#pragma incomplete Imap #pragma incomplete Imap
@ -45,19 +47,6 @@ struct Label
ulong pc; ulong pc;
}; };
/*
* Proc.fpstate
*/
enum
{
/* Floating point states */
FPinit = 0,
FPactive = 1,
FPinactive = 2,
/* Bit that's or-ed in during note handling (FP is illegal in note handlers) */
FPillegal = 0x100,
};
/* /*
* This structure must agree with fpsave and fprestore asm routines * This structure must agree with fpsave and fprestore asm routines
*/ */
@ -73,15 +62,36 @@ struct FPsave
}; };
}; };
struct PFPU
{
int fpstate;
FPsave fpsave[1];
};
enum
{
/* Floating point states */
FPinit = 0,
FPactive = 1,
FPinactive = 2,
/* Bit that's or-ed in during note handling (FP is illegal in note handlers) */
FPillegal = 0x100,
};
struct Confmem
{
ulong base;
ulong npage;
ulong kbase;
ulong klimit;
};
struct Conf struct Conf
{ {
ulong nmach; /* processors */ ulong nmach; /* processors */
ulong nproc; /* processes */ ulong nproc; /* processes */
ulong npage0; /* total physical pages of memory */ Confmem mem[2];
ulong npage1; /* total physical pages of memory */
ulong npage; /* total physical pages of memory */ ulong npage; /* total physical pages of memory */
ulong base0; /* base of bank 0 */
ulong base1; /* base of bank 1 */
ulong upages; /* user page pool */ ulong upages; /* user page pool */
ulong nimage; /* number of page cache image headers */ ulong nimage; /* number of page cache image headers */
ulong nswap; /* number of swap pages */ ulong nswap; /* number of swap pages */
@ -102,14 +112,6 @@ struct PMMU
Ureg *mmureg; /* pointer to ureg structure */ Ureg *mmureg; /* pointer to ureg structure */
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave
{
ulong UNUSED;
};
#include "../port/portdat.h" #include "../port/portdat.h"
/* /*

View file

@ -292,7 +292,7 @@ procsave(Proc *p)
p->kentry -= t; p->kentry -= t;
if(p->fpstate == FPactive){ if(p->fpstate == FPactive){
if(p->state != Moribund) if(p->state != Moribund)
fpsave(&up->fpsave); fpsave(up->fpsave);
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
} }

View file

@ -101,6 +101,6 @@ init.h: ../port/initcode.c init9.s
$AS init9.s $AS init9.s
$LD -l -s -R4 -o init.out init9.$O initcode.$O /power/lib/libc.a $LD -l -s -R4 -o init.out init9.$O initcode.$O /power/lib/libc.a
{echo 'uchar initcode[]={' {echo 'uchar initcode[]={'
strip < init.out | xd -1x | <init.out xd -1x |
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g' sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
echo '};'} > init.h echo '};'} > init.h

View file

@ -243,7 +243,7 @@ trap(Ureg *ureg)
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPinactive: case FPinactive:
fprestore(&up->fpsave); fprestore(up->fpsave);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPactive: case FPactive:
@ -711,7 +711,7 @@ notify(Ureg* ur)
return 0; return 0;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;

View file

@ -1,6 +1,7 @@
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct KMap KMap; typedef struct KMap KMap;
typedef struct Lance Lance; typedef struct Lance Lance;
typedef struct Lancemem Lancemem; typedef struct Lancemem Lancemem;
@ -8,7 +9,6 @@ typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct MMU MMU; typedef struct MMU MMU;
typedef struct Notsave Notsave;
typedef struct PMMU PMMU; typedef struct PMMU PMMU;
typedef struct Softtlb Softtlb; typedef struct Softtlb Softtlb;
typedef struct Ureg Ureg; typedef struct Ureg Ureg;
@ -73,18 +73,6 @@ struct Conf
/* /*
* floating point registers * floating point registers
*/ */
enum
{
/* floating point state */
FPinit,
FPactive,
FPinactive,
FPemu,
/* bit meaning floating point illegal */
FPillegal= 0x100,
};
enum { enum {
Nfpregs = 32, /* floats; half as many doubles */ Nfpregs = 32, /* floats; half as many doubles */
}; };
@ -111,6 +99,24 @@ struct FPsave
int fpcnt; /* how many consecutive at that addr */ int fpcnt; /* how many consecutive at that addr */
}; };
struct PFPU
{
int fpstate;
FPsave fpsave[1];
};
enum
{
/* floating point state */
FPinit,
FPactive,
FPinactive,
FPemu,
/* bit meaning floating point illegal */
FPillegal= 0x100,
};
/* /*
* mmu goo in the Proc structure * mmu goo in the Proc structure
*/ */
@ -119,14 +125,6 @@ struct PMMU
int pidonmach[MAXMACH]; int pidonmach[MAXMACH];
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave
{
ulong nonempty;
};
#include "../port/portdat.h" #include "../port/portdat.h"
struct Mach struct Mach

View file

@ -29,7 +29,7 @@ fptrap(Ureg *ur)
{ {
ulong iw, npc; ulong iw, npc;
if((up->fpsave.fpstatus&(1<<17)) == 0) if((up->fpsave->fpstatus&(1<<17)) == 0)
return; return;
if(ur->cause & (1<<31)) if(ur->cause & (1<<31))
@ -41,7 +41,7 @@ fptrap(Ureg *ur)
return; return;
if(ur->cause & (1<<31)){ if(ur->cause & (1<<31)){
npc = branch(ur, up->fpsave.fpstatus); npc = branch(ur, up->fpsave->fpstatus);
if(npc == 0) if(npc == 0)
return; return;
ur->pc = npc; ur->pc = npc;
@ -49,7 +49,7 @@ fptrap(Ureg *ur)
else else
ur->pc += 4; ur->pc += 4;
up->fpsave.fpstatus &= ~(1<<17); up->fpsave->fpstatus &= ~(1<<17);
} }
static void static void
@ -107,8 +107,8 @@ fpunimp(ulong iw)
ft = (iw>>16) & ((1<<5)-1); ft = (iw>>16) & ((1<<5)-1);
fs = (iw>>11) & ((1<<5)-1); fs = (iw>>11) & ((1<<5)-1);
fd = (iw>>6) & ((1<<5)-1); fd = (iw>>6) & ((1<<5)-1);
unpack(&up->fpsave, fmt, fs, &ss, &es); unpack(up->fpsave, fmt, fs, &ss, &es);
unpack(&up->fpsave, fmt, ft, &st, &et); unpack(up->fpsave, fmt, ft, &st, &et);
ed = 0; ed = 0;
maxe = 0; maxe = 0;
maxm = 0; maxm = 0;
@ -124,11 +124,11 @@ fpunimp(ulong iw)
} }
switch(op){ switch(op){
case ABS: case ABS:
up->fpsave.reg[fd] &= ~0x80000000; up->fpsave->reg[fd] &= ~0x80000000;
return 1; return 1;
case NEG: case NEG:
up->fpsave.reg[fd] ^= 0x80000000; up->fpsave->reg[fd] ^= 0x80000000;
return 1; return 1;
case SUB: case SUB:
@ -164,9 +164,9 @@ fpunimp(ulong iw)
return 0; return 0;
} }
if(ed <= -(maxe-5)){ /* guess: underflow */ if(ed <= -(maxe-5)){ /* guess: underflow */
zeroreg(&up->fpsave, fmt, fd, sd); zeroreg(up->fpsave, fmt, fd, sd);
/* Set underflow exception and sticky */ /* Set underflow exception and sticky */
up->fpsave.fpstatus |= (1<<3)|(1<<13); up->fpsave->fpstatus |= (1<<3)|(1<<13);
return 1; return 1;
} }
return 0; return 0;

View file

@ -396,7 +396,7 @@ void
procsetup(Proc *p) procsetup(Proc *p)
{ {
p->fpstate = FPinit; p->fpstate = FPinit;
p->fpsave = initfp; memmove(p->fpsave, &initfp, sizeof(FPsave));
cycles(&p->kentry); cycles(&p->kentry);
p->pcycles = -p->kentry; p->pcycles = -p->kentry;
@ -413,11 +413,11 @@ procfork(Proc *p)
s = splhi(); s = splhi();
switch(up->fpstate & ~FPillegal){ switch(up->fpstate & ~FPillegal){
case FPactive: case FPactive:
savefpregs(&up->fpsave); savefpregs(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
/* wet floor */ /* wet floor */
case FPinactive: case FPinactive:
p->fpsave = up->fpsave; memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
splx(s); splx(s);
@ -430,7 +430,7 @@ procsave(Proc *p)
if(p->fpstate == FPactive){ if(p->fpstate == FPactive){
if(p->state != Moribund) { if(p->state != Moribund) {
savefpregs(&p->fpsave); savefpregs(p->fpsave);
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
} }

View file

@ -212,7 +212,7 @@ trap(Ureg *ur)
if(!user) if(!user)
goto Default; goto Default;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
savefpregs(&up->fpsave); savefpregs(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
clrfpintr(); clrfpintr();
@ -257,7 +257,7 @@ trap(Ureg *ur)
break; break;
} }
if(up->fpstate == FPinit || up->fpstate == FPinactive){ if(up->fpstate == FPinit || up->fpstate == FPinactive){
restfpregs(&up->fpsave, up->fpsave.fpstatus&~FPEXPMASK); restfpregs(up->fpsave, up->fpsave->fpstatus&~FPEXPMASK);
up->fpstate = FPactive; up->fpstate = FPactive;
ur->status |= CU1; ur->status |= CU1;
break; break;
@ -289,7 +289,7 @@ trap(Ureg *ur)
} }
if(fpchk) { if(fpchk) {
fpfcr31 = up->fpsave.fpstatus; fpfcr31 = up->fpsave->fpstatus;
if((fpfcr31>>12) & ((fpfcr31>>7)|0x20) & 0x3f) { if((fpfcr31>>12) & ((fpfcr31>>7)|0x20) & 0x3f) {
spllo(); spllo();
fpexcep = fpexcname(ur, fpfcr31, buf1, sizeof buf1); fpexcep = fpexcname(ur, fpfcr31, buf1, sizeof buf1);
@ -501,7 +501,7 @@ notify(Ureg *ur)
return 0; return 0;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
savefpregs(&up->fpsave); savefpregs(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;

View file

@ -24,6 +24,7 @@ enum {
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct ISAConf ISAConf; typedef struct ISAConf ISAConf;
typedef struct Isolated Isolated; typedef struct Isolated Isolated;
typedef struct Label Label; typedef struct Label Label;
@ -33,7 +34,6 @@ typedef struct Memcache Memcache;
typedef struct MMMU MMMU; typedef struct MMMU MMMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef u32int Mreg; /* Msr - bloody UART */ typedef u32int Mreg; /* Msr - bloody UART */
typedef struct Notsave Notsave;
typedef struct Page Page; typedef struct Page Page;
typedef struct Pcisiz Pcisiz; typedef struct Pcisiz Pcisiz;
typedef struct Pcidev Pcidev; typedef struct Pcidev Pcidev;
@ -72,14 +72,14 @@ struct Label
uintptr pc; uintptr pc;
}; };
/*
* emulated or vfp3 floating point
*/
enum { enum {
Maxfpregs = 32, /* could be 16 or 32, see Mach.fpnregs */ Maxfpregs = 32, /* could be 16 or 32, see Mach.fpnregs */
Nfpctlregs = 16, Nfpctlregs = 16,
}; };
/*
* emulated or vfp3 floating point
*/
struct FPsave struct FPsave
{ {
ulong status; ulong status;
@ -94,9 +94,12 @@ struct FPsave
uintptr pc; /* of failed fp instr. */ uintptr pc; /* of failed fp instr. */
}; };
/* struct PFPU
* FPsave.fpstate {
*/ int fpstate;
FPsave fpsave[1];
};
enum enum
{ {
FPinit, FPinit,
@ -135,13 +138,6 @@ struct Conf
int monitor; /* flag */ int monitor; /* flag */
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave {
int emptiness;
};
/* /*
* MMU stuff in Mach. * MMU stuff in Mach.
*/ */

View file

@ -650,7 +650,7 @@ fpiarm(Ureg *ur)
if(up == nil) if(up == nil)
panic("fpiarm not in a process"); panic("fpiarm not in a process");
ufp = &up->fpsave; ufp = up->fpsave;
/* /*
* because all the emulated fp state is in the proc structure, * because all the emulated fp state is in the proc structure,
* it need not be saved/restored * it need not be saved/restored

View file

@ -450,7 +450,7 @@ mathnote(void)
ulong status; ulong status;
char *msg, note[ERRMAX]; char *msg, note[ERRMAX];
status = up->fpsave.status; status = up->fpsave->status;
/* /*
* Some attention should probably be paid here to the * Some attention should probably be paid here to the
@ -473,7 +473,7 @@ mathnote(void)
msg = "invalid operation"; msg = "invalid operation";
} }
snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux", snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux",
msg, up->fpsave.pc, status); msg, up->fpsave->pc, status);
postnote(up, 1, note, NDebug); postnote(up, 1, note, NDebug);
} }
@ -493,12 +493,12 @@ matherror(Ureg *ur, void*)
/* /*
* save floating point state to check out error * save floating point state to check out error
*/ */
fpenv(&up->fpsave); fpenv(up->fpsave);
mathnote(); mathnote();
if(ur->pc & KZERO) if(ur->pc & KZERO)
panic("fp: status %ux fppc=0x%lux pc=0x%lux", panic("fp: status %ux fppc=0x%lux pc=0x%lux",
up->fpsave.status, up->fpsave.pc, ur->pc); up->fpsave->status, up->fpsave->pc, ur->pc);
} }
/* /*
@ -515,6 +515,8 @@ mathemu(Ureg *ureg, void*)
switch(up->fpstate){ switch(up->fpstate){
case FPinit: case FPinit:
fpinit(); fpinit();
while(up->fpsave == nil)
up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPinactive: case FPinactive:
@ -525,11 +527,11 @@ mathemu(Ureg *ureg, void*)
* More attention should probably be paid here to the * More attention should probably be paid here to the
* exception masks and error summary. * exception masks and error summary.
*/ */
if((up->fpsave.status & ~up->fpsave.control) & 0x07F){ if((up->fpsave->status & ~up->fpsave->control) & 0x07F){
mathnote(); mathnote();
break; break;
} }
fprestore(&up->fpsave); fprestore(up->fpsave);
up->fpstate = FPactive; up->fpstate = FPactive;
break; break;
case FPactive: case FPactive:
@ -580,10 +582,12 @@ procfork(Proc *p)
s = splhi(); s = splhi();
switch(up->fpstate & ~FPillegal){ switch(up->fpstate & ~FPillegal){
case FPactive: case FPactive:
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
case FPinactive: case FPinactive:
p->fpsave = up->fpsave; while(p->fpsave == nil)
p->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
splx(s); splx(s);
@ -622,7 +626,7 @@ procsave(Proc *p)
* until the process runs again and generates an * until the process runs again and generates an
* emulation fault to activate the FPU. * emulation fault to activate the FPU.
*/ */
fpsave(&p->fpsave); fpsave(p->fpsave);
} }
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }

View file

@ -674,7 +674,7 @@ syscall(Ureg* ureg)
scallnr = ureg->ax; scallnr = ureg->ax;
up->scallnr = scallnr; up->scallnr = scallnr;
if(scallnr == RFORK && up->fpstate == FPactive){ if(scallnr == RFORK && up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
spllo(); spllo();
@ -764,7 +764,7 @@ notify(Ureg* ureg)
return 0; return 0;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;

View file

@ -1,13 +1,13 @@
typedef struct Conf Conf; typedef struct Conf Conf;
typedef struct Confmem Confmem; typedef struct Confmem Confmem;
typedef struct FPsave FPsave; typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct L1 L1; typedef struct L1 L1;
typedef struct Label Label; typedef struct Label Label;
typedef struct Lock Lock; typedef struct Lock Lock;
typedef struct KMap KMap; typedef struct KMap KMap;
typedef struct MMMU MMMU; typedef struct MMMU MMMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct Page Page; typedef struct Page Page;
typedef struct Proc Proc; typedef struct Proc Proc;
typedef struct PMMU PMMU; typedef struct PMMU PMMU;
@ -43,9 +43,12 @@ struct FPsave
uchar regs[256]; uchar regs[256];
}; };
/* struct PFPU
* FPsave.status {
*/ int fpstate;
FPsave fpsave[1];
};
enum enum
{ {
FPinit, FPinit,
@ -79,13 +82,6 @@ struct Conf
int monitor; int monitor;
}; };
/*
* things saved in the Proc structure during a notify
*/
struct Notsave {
int emptiness;
};
/* /*
* MMU stuff in proc * MMU stuff in proc
*/ */

View file

@ -50,10 +50,10 @@ procfork(Proc *p)
s = splhi(); s = splhi();
switch(up->fpstate & ~FPillegal){ switch(up->fpstate & ~FPillegal){
case FPactive: case FPactive:
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
case FPinactive: case FPinactive:
p->fpsave = up->fpsave; memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
splx(s); splx(s);

View file

@ -134,7 +134,7 @@ mathtrap(Ureg *, ulong)
break; break;
case FPinactive: case FPinactive:
s = splhi(); s = splhi();
fprestore(&up->fpsave); fprestore(up->fpsave);
up->fpstate = FPactive; up->fpstate = FPactive;
splx(s); splx(s);
break; break;
@ -304,7 +304,7 @@ notify(Ureg *ureg)
return 0; return 0;
if(up->fpstate == FPactive){ if(up->fpstate == FPactive){
fpsave(&up->fpsave); fpsave(up->fpsave);
up->fpstate = FPinactive; up->fpstate = FPinactive;
} }
up->fpstate |= FPillegal; up->fpstate |= FPillegal;
@ -517,7 +517,7 @@ procsave(Proc *p)
if(p->state == Moribund) if(p->state == Moribund)
fpclear(); fpclear();
else else
fpsave(&p->fpsave); fpsave(p->fpsave);
p->fpstate = FPinactive; p->fpstate = FPinactive;
} }
cycles(&t); cycles(&t);