sync with 9 Reference: /n/patches.lsub.org/patch/plan9-20120424 Date: Tue Apr 24 20:36:22 CES 2012 Signed-off-by: nemo@lsub.org --- /sys/src/9/pc/dat.h Thu Apr 19 15:29:43 2012 +++ /sys/src/9/pc/dat.h Tue Apr 24 19:46:06 2012 @@ -2,8 +2,7 @@ typedef struct BIOS32ci BIOS32ci; typedef struct Conf Conf; typedef struct Confmem Confmem; -typedef union FPanystate FPanystate; -typedef struct FPsave FPsave; +typedef union FPsave FPsave; typedef struct FPssestate FPssestate; typedef struct FPstate FPstate; typedef struct ISAConf ISAConf; @@ -87,7 +86,7 @@ uchar regs[80]; /* floating point registers */ }; -struct FPssestate /* SSE fp state */ +struct FPssestate /* SSE fp state */ { ushort fcw; /* control */ ushort fsw; /* status */ @@ -102,19 +101,18 @@ ulong mxcsr; /* MXCSR register state */ ulong mxcsr_mask; /* MXCSR mask register */ uchar xregs[480]; /* extended registers */ + uchar alignpad[FPalign]; }; -#define FPalign 16 /* required for FXSAVE */ - -union FPanystate { +/* + * the FP regs must be stored here, not somewhere pointed to from here. + * port code assumes this. + */ +union FPsave { FPstate; FPssestate; }; -struct FPsave { - FPanystate *addr; /* addr of fp state if it is alloced */ -}; - struct Confmem { ulong base; @@ -256,6 +254,7 @@ uvlong tscticks; int pdballoc; int pdbfree; + FPsave *fpsavalign; vlong mtrrcap; vlong mtrrdef; --- /sys/src/9/pc/fns.h Thu Apr 19 15:29:43 2012 +++ /sys/src/9/pc/fns.h Tue Apr 24 19:46:06 2012 @@ -34,7 +34,9 @@ void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); void fpsserestore(FPsave*); +void fpsserestore0(FPsave*); void fpssesave(FPsave*); +void fpssesave0(FPsave*); ulong fpstatus(void); void fpx87restore(FPsave*); void fpx87save(FPsave*); --- /sys/src/9/pc/l.s Thu Apr 19 15:29:43 2012 +++ /sys/src/9/pc/l.s Tue Apr 24 19:46:06 2012 @@ -784,19 +784,15 @@ WAIT RET -/* fpx87save(&fpstateptr) */ TEXT fpx87save(SB), $0 /* save state and disable */ MOVL p+0(FP), AX /* points to pointer */ - MOVL (AX), AX /* now points to state buffer */ FSAVE 0(AX) /* no WAIT */ FPOFF RET -/* fpx87restore(&fpstateptr) */ TEXT fpx87restore(SB), $0 /* enable and restore state */ FPON - MOVL p+0(FP), AX /* points to pointer */ - MOVL (AX), AX /* now points to state buffer */ + MOVL p+0(FP), AX FRSTOR 0(AX) WAIT RET @@ -805,10 +801,8 @@ FSTSW AX RET -/* fpenv(&fpstateptr) */ TEXT fpenv(SB), $0 /* save state without waiting */ - MOVL p+0(FP), AX /* points to pointer */ - MOVL (AX), AX /* now points to state buffer */ + MOVL p+0(FP), AX FSTENV 0(AX) RET @@ -818,19 +812,15 @@ FPOFF RET -/* fpssesave(&fpstateptr) */ -TEXT fpssesave(SB), $0 /* save state and disable */ - MOVL p+0(FP), AX /* points to pointer */ - MOVL (AX), AX /* now points to state buffer */ +TEXT fpssesave0(SB), $0 /* save state and disable */ + MOVL p+0(FP), AX FXSAVE /* no WAIT */ FPOFF RET -/* fpsserestore(&fpstateptr) */ -TEXT fpsserestore(SB), $0 /* enable and restore state */ +TEXT fpsserestore0(SB), $0 /* enable and restore state */ FPON - MOVL p+0(FP), AX /* points to pointer */ - MOVL (AX), AX /* now points to state buffer */ + MOVL p+0(FP), AX FXRSTOR WAIT RET --- /sys/src/9/pc/main.c Thu Apr 19 15:29:43 2012 +++ /sys/src/9/pc/main.c Thu Apr 26 11:32:46 2012 @@ -466,10 +466,10 @@ }; static void -mathstate(ulong *status, ulong *pc, ulong *control) +mathstate(ulong *stsp, ulong *pcp, ulong *ctlp) { ulong sts, fpc, ctl; - FPanystate *f = (FPanystate *)up->fpsave.addr; + FPsave *f = &up->fpsave; if(fpsave == fpx87save){ sts = f->status; @@ -480,12 +480,12 @@ fpc = f->fpuip; ctl = f->fcw; } - if(status) - *status = sts; - if(pc) - *pc = fpc; - if(control) - *control = ctl; + if(stsp) + *stsp = sts; + if(pcp) + *pcp = fpc; + if(ctlp) + *ctlp = ctl; } static void @@ -517,28 +517,46 @@ }else msg = "invalid operation"; } - snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux", + snprint(note, sizeof note, "sys: fp: %s fppc=%#lux status=%#lux", msg, pc, status); postnote(up, 1, note, NDebug); } -static void -fpexit(void) +/* + * 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) { - free(up->fpsave.addr); - up->fpsave.addr = nil; + 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); } -static void* -fpalloc(void) +void +fpsserestore(FPsave *fps) { - if(up->fpsave.addr == nil) { - up->fpsave.addr = fpsave == fpx87save? smalloc(sizeof(FPstate)): - mallocalign(sizeof(FPssestate), FPalign, 0, 0); - if (up->fpsave.addr) - up->fpexit = fpexit; - } - return up->fpsave.addr; + 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 */ + 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) + memmove(fps, afps, sizeof(FPssestate) - FPalign); } /* @@ -556,8 +574,6 @@ if(!(m->cpuiddx & 0x01)) outb(0xF0, 0xFF); - fpalloc(); - /* * save floating point state to check out error */ @@ -585,7 +601,6 @@ } switch(up->fpstate){ case FPinit: - fpalloc(); fpinit(); up->fpstate = FPactive; break; @@ -606,7 +621,7 @@ up->fpstate = FPactive; break; case FPactive: - panic("math emu pid %ld %s pc 0x%lux", + panic("math emu pid %ld %s pc %#lux", up->pid, up->text, ureg->pc); break; } @@ -674,8 +689,7 @@ * until the process runs again and generates an * emulation fault to activate the FPU. */ - if(p->fpsave.addr != nil) - fpsave(&p->fpsave); + fpsave(&p->fpsave); } p->fpstate = FPinactive; } --- /sys/src/9/pc/mem.h Thu Apr 12 12:25:06 2012 +++ /sys/src/9/pc/mem.h Tue Apr 24 19:46:07 2012 @@ -20,6 +20,7 @@ #define PGROUND(s) ROUND(s, BY2PG) #define CACHELINESZ 32 /* pentium & later */ #define BLOCKALIGN 8 +#define FPalign 16 /* required for FXSAVE */ /* * In 32-bit mode, the MAXMACH limit is 32 without --- /sys/src/9/port/portdat.h Thu Apr 19 15:29:43 2012 +++ /sys/src/9/port/portdat.h Tue Apr 24 19:46:07 2012 @@ -707,7 +707,6 @@ void *kparg; FPsave fpsave; /* address of this is known by db */ - void (*fpexit)(void); /* if non-nil, called by pexit */ int scallnr; /* sys call number - known by db */ Sargs s; /* address of this is known by db */ int nerrlab; --- /sys/src/9/port/proc.c Thu Apr 19 15:29:43 2012 +++ /sys/src/9/port/proc.c Tue Apr 24 19:46:07 2012 @@ -1047,9 +1047,6 @@ if(up->syscalltrace) free(up->syscalltrace); - up->fpstate = FPinit; - if(up->fpexit) - up->fpexit(); up->alarm = 0; if (up->tt) timerdel(up);