shithub: riscv

Download patch

ref: 6eca75fafb0b125329592b5b2c1b0fcb52c0bd7f
parent: 778361655065b80021d7b593b0afe2c10fe99eec
parent: 24057fd4f494a00573d34adeaa7042721c1a06a0
author: cinap_lenrek <[email protected]>
date: Sat Nov 4 16:11:20 EDT 2017

merge

--- a/sys/man/8/tinc
+++ b/sys/man/8/tinc
@@ -1,6 +1,6 @@
 .TH TINC 8
 .SH NAME
-tinc - mash peer to peer VPN
+tinc - mesh peer to peer VPN
 .SH SYNOPSIS
 .B ip/tinc
 [
@@ -27,7 +27,7 @@
 .I hosts...
 ]
 .SH DESCRIPTION
-Tinc implements the mash peer to peer VPN protocol from
+Tinc implements the mesh peer to peer VPN protocol from
 .I https://www.tinc-vpn.org/
 as of version 1.0.32. Within a tinc VPN one can reach all
 the subnets of all hosts within the network even when not
--- a/sys/src/9/bcm/dat.h
+++ b/sys/src/9/bcm/dat.h
@@ -15,6 +15,7 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
@@ -21,7 +22,6 @@
 typedef struct Memcache	Memcache;
 typedef struct MMMU	MMMU;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct Page	Page;
 typedef struct PhysUart	PhysUart;
 typedef struct PMMU	PMMU;
@@ -56,14 +56,14 @@
 	uintptr	pc;
 };
 
+/*
+ * emulated or vfp3 floating point
+ */
 enum {
 	Maxfpregs	= 32,	/* could be 16 or 32, see Mach.fpnregs */
 	Nfpctlregs	= 16,
 };
 
-/*
- * emulated or vfp3 floating point
- */
 struct FPsave
 {
 	ulong	status;
@@ -78,9 +78,12 @@
 	uintptr	pc;		/* of failed fp instr. */
 };
 
-/*
- * FPsave.fpstate
- */
+struct PFPU
+{
+	int	fpstate;
+	FPsave	fpsave[1];
+};
+
 enum
 {
 	FPinit,
@@ -117,13 +120,6 @@
 	ulong	hz;		/* processor cycle freq */
 	ulong	mhz;
 	int	monitor;	/* flag */
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
 };
 
 /*
--- a/sys/src/9/bcm/fpiarm.c
+++ b/sys/src/9/bcm/fpiarm.c
@@ -650,7 +650,7 @@
 
 	if(up == nil)
 		panic("fpiarm not in a process");
-	ufp = &up->fpsave;
+	ufp = up->fpsave;
 	/*
 	 * because all the emulated fp state is in the proc structure,
 	 * it need not be saved/restored
--- a/sys/src/9/bcm/vfp3.c
+++ b/sys/src/9/bcm/vfp3.c
@@ -222,7 +222,7 @@
 fpunotify(Ureg*)
 {
 	if(up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
@@ -259,11 +259,11 @@
 	int n;
 
 	fpon();
-	fpwr(Fpscr, p->fpsave.control);
+	fpwr(Fpscr, p->fpsave->control);
 	m->fpscr = fprd(Fpscr) & ~Allcc;
 	assert(m->fpnregs);
 	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 @@
 			 * until the process runs again and generates an
 			 * emulation fault to activate the FPU.
 			 */
-			fpsave(&p->fpsave);
+			fpsave(p->fpsave);
 		}
 		p->fpstate = FPinactive;
 	}
@@ -317,11 +317,11 @@
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 		/* no break */
 	case FPinactive:
-		p->fpsave = up->fpsave;
+		memmove(p->fpsave, up->fpsave, sizeof(FPsave));
 		p->fpstate = FPinactive;
 	}
 	splx(s);
@@ -345,7 +345,7 @@
 	ulong status;
 	char *msg, note[ERRMAX];
 
-	status = up->fpsave.status;
+	status = up->fpsave->status;
 
 	/*
 	 * Some attention should probably be paid here to the
@@ -364,7 +364,7 @@
 	else
 		msg = "spurious";
 	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);
 }
 
@@ -388,7 +388,7 @@
 		 * More attention should probably be paid here to the
 		 * exception masks and error summary.
 		 */
-		if(up->fpsave.status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){
+		if(up->fpsave->status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){
 			mathnote();
 			break;
 		}
--- a/sys/src/9/kw/dat.h
+++ b/sys/src/9/kw/dat.h
@@ -1,6 +1,7 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
@@ -7,7 +8,6 @@
 typedef struct Memcache	Memcache;
 typedef struct MMMU	MMMU;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct Page	Page;
 typedef struct Pcidev	Pcidev;
 typedef struct PhysUart	PhysUart;
@@ -45,13 +45,13 @@
 	uintptr	pc;
 };
 
+/*
+ * emulated floating point
+ */
 enum{
 	Nfpctlregs = 16,
 };
 
-/*
- * emulated floating point
- */
 struct FPsave
 {
 	ulong	status;
@@ -61,9 +61,12 @@
 	int	fpstate;
 };
 
-/*
- * FPsave.status
- */
+struct PFPU
+{
+	int	fpstate;
+	FPsave	fpsave[1];
+};
+
 enum
 {
 	FPinit,
@@ -96,13 +99,6 @@
 	int	nswppo;		/* max # of pageouts per segment pass */
 //	ulong	hz;		/* processor cycle freq */
 //	ulong	mhz;
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
 };
 
 /*
--- a/sys/src/9/kw/fpiarm.c
+++ b/sys/src/9/kw/fpiarm.c
@@ -726,7 +726,7 @@
 
 	if(up == nil)
 		panic("fpiarm not in a process");
-	ufp = &up->fpsave;
+	ufp = up->fpsave;
 	/*
 	 * because all the emulated fp state is in the proc structure,
 	 * it need not be saved/restored
--- a/sys/src/9/mtx/dat.h
+++ b/sys/src/9/mtx/dat.h
@@ -1,11 +1,11 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct Page	Page;
 typedef struct PCArch	PCArch;
 typedef struct Pcidev	Pcidev;
@@ -46,16 +46,6 @@
 };
 
 /*
- * Proc.fpstate
- */
-enum
-{
-	FPinit,
-	FPactive,
-	FPinactive,
-};
-
-/*
  * This structure must agree with fpsave and fprestore asm routines
  */
 struct	FPsave
@@ -70,6 +60,19 @@
 	};
 };
 
+struct	PFPU
+{
+	int	fpstate;
+	FPsave	fpsave[1];
+};
+
+enum
+{
+	FPinit,
+	FPactive,
+	FPinactive,
+};
+
 struct Confmem
 {
 	ulong	base;
@@ -101,14 +104,6 @@
 struct PMMU
 {
 	int	mmupid;
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave
-{
-	ulong	UNUSED;
 };
 
 #include "../port/portdat.h"
--- a/sys/src/9/mtx/main.c
+++ b/sys/src/9/mtx/main.c
@@ -241,7 +241,7 @@
 {
 	if(p->fpstate == FPactive){
 		if(p->state != Moribund)
-			fpsave(&up->fpsave);
+			fpsave(up->fpsave);
 		p->fpstate = FPinactive;
 	}
 }
--- a/sys/src/9/mtx/trap.c
+++ b/sys/src/9/mtx/trap.c
@@ -246,7 +246,7 @@
 			up->fpstate = FPactive;
 			break;
 		case FPinactive:
-			fprestore(&up->fpsave);
+			fprestore(up->fpsave);
 			up->fpstate = FPactive;
 			break;
 		default:
--- a/sys/src/9/omap/dat.h
+++ b/sys/src/9/omap/dat.h
@@ -27,6 +27,7 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
@@ -34,7 +35,6 @@
 typedef struct MMMU	MMMU;
 typedef struct Mach	Mach;
 typedef u32int Mreg;				/* Msr - bloody UART */
-typedef struct Notsave	Notsave;
 typedef struct Page	Page;
 typedef struct PhysUart	PhysUart;
 typedef struct PMMU	PMMU;
@@ -69,13 +69,13 @@
 	uintptr	pc;
 };
 
+/*
+ * emulated floating point
+ */
 enum{
 	Nfpctlregs = 16,
 };
 
-/*
- * emulated floating point
- */
 struct FPsave
 {
 	ulong	status;
@@ -85,9 +85,12 @@
 	int	fpstate;
 };
 
-/*
- * FPsave.status
- */
+struct PFPU
+{
+	int	fpstate;
+	FPsave	fpsave[1];
+};
+
 enum
 {
 	FPinit,
@@ -120,13 +123,6 @@
 	ulong	hz;		/* processor cycle freq */
 	ulong	mhz;
 	int	monitor;	/* flag */
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
 };
 
 /*
--- a/sys/src/9/omap/fpiarm.c
+++ b/sys/src/9/omap/fpiarm.c
@@ -726,7 +726,7 @@
 
 	if(up == nil)
 		panic("fpiarm not in a process");
-	ufp = &up->fpsave;
+	ufp = up->fpsave;
 	/*
 	 * because all the emulated fp state is in the proc structure,
 	 * it need not be saved/restored
--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -3,14 +3,14 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef union FPsave	FPsave;
+typedef struct FPx87state FPx87state;
 typedef struct FPssestate FPssestate;
-typedef struct FPstate	FPstate;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
 typedef struct MMU	MMU;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct PCArch	PCArch;
 typedef struct Pcidev	Pcidev;
 typedef struct PCMmap	PCMmap;
@@ -51,23 +51,8 @@
 	ulong	pc;
 };
 
-
-/*
- * FPsave.status
- */
-enum
+struct	FPx87state		/* x87 fp state */
 {
-	/* 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	r1;
 	ushort	status;
@@ -98,18 +83,30 @@
 	ulong	mxcsr;		/* MXCSR register state */
 	ulong	mxcsr_mask;	/* MXCSR mask register */
 	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 {
-	FPstate;
+	FPx87state;
 	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
 {
 	ulong	base;
@@ -162,16 +159,6 @@
 	
 	u32int	dr[8];			/* debug registers */
 	void	*vmx;
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave
-{
-	ulong	svflags;
-	ulong	svcs;
-	ulong	svss;
 };
 
 #include "../port/portdat.h"
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -40,9 +40,7 @@
 void	(*fprestore)(FPsave*);
 void	(*fpsave)(FPsave*);
 void	fpsserestore(FPsave*);
-void	fpsserestore0(FPsave*);
 void	fpssesave(FPsave*);
-void	fpssesave0(FPsave*);
 void	fpx87restore(FPsave*);
 void	fpx87restore0(FPsave*);
 void	fpx87save(FPsave*);
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -622,13 +622,13 @@
 	FPOFF
 	RET
 
-TEXT fpssesave0(SB), $0				/* save state and disable */
+TEXT fpssesave(SB), $0				/* save state and disable */
 	MOVL	p+0(FP), AX
 	FXSAVE	0(AX)				/* no WAIT */
 	FPOFF
 	RET
 
-TEXT fpsserestore0(SB), $0			/* enable and restore state */
+TEXT fpsserestore(SB), $0			/* enable and restore state */
 	FPON
 	MOVL	p+0(FP), AX
 	FXRSTOR	0(AX)
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -311,12 +311,8 @@
 }
 
 /*
- * 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.
- *
- * 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
 fpx87save(FPsave *fps)
@@ -441,32 +437,6 @@
 	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[] =
 {
 	nil,	/* handled below */
@@ -524,9 +494,9 @@
 	/*
 	 *  get floating point state to check out error
 	 */
-	fpsave(&up->fpsave);
+	fpsave(up->fpsave);
 	up->fpstate = FPinactive;
-	mathnote(up->fpsave.fsw, up->fpsave.fpuip);
+	mathnote(up->fpsave->fsw, up->fpsave->fpuip);
 }
 
 /*
@@ -535,9 +505,9 @@
 static void
 simderror(Ureg *ureg, void*)
 {
-	fpsave(&up->fpsave);
+	fpsave(up->fpsave);
 	up->fpstate = FPinactive;
-	mathnote(up->fpsave.mxcsr & 0x3f, ureg->pc);
+	mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc);
 }
 
 /*
@@ -558,6 +528,8 @@
 		fpinit();
 		if(fpsave == fpssesave)
 			ldmxcsr(0);	/* no simd exceptions on 386 */
+		while(up->fpsave == nil)
+			up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
 		up->fpstate = FPactive;
 		break;
 	case FPinactive:
@@ -568,13 +540,13 @@
 		 * More attention should probably be paid here to the
 		 * exception masks and error summary.
 		 */
-		status = up->fpsave.fsw;
-		control = up->fpsave.fcw;
+		status = up->fpsave->fsw;
+		control = up->fpsave->fcw;
 		if((status & ~control) & 0x07F){
-			mathnote(status, up->fpsave.fpuip);
+			mathnote(status, up->fpsave->fpuip);
 			break;
 		}
-		fprestore(&up->fpsave);
+		fprestore(up->fpsave);
 		up->fpstate = FPactive;
 		break;
 	case FPactive:
@@ -645,10 +617,12 @@
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = 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;
 	}
 	
@@ -708,7 +682,7 @@
 			 * until the process runs again and generates an
 			 * emulation fault to activate the FPU.
 			 */
-			fpsave(&p->fpsave);
+			fpsave(p->fpsave);
 		}
 		p->fpstate = FPinactive;
 	}
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -854,7 +854,7 @@
 		return 0;
 
 	if(up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -2,15 +2,13 @@
 typedef struct BIOS32ci	BIOS32ci;
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
-typedef union  FPsave	FPsave;
-typedef struct Fxsave	Fxsave;
-typedef struct FPstate	FPstate;
+typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
 typedef struct MMU	MMU;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct PCArch	PCArch;
 typedef struct Pcidev	Pcidev;
 typedef struct PCMmap	PCMmap;
@@ -51,25 +49,8 @@
 	uintptr	pc;
 };
 
-/*
- * FPsave.status
- */
-enum
+struct FPsave
 {
-	/* 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	fsw;			/* x87 status word */
 	u8int	ftw;			/* x87 tag word */
@@ -84,11 +65,23 @@
 	uchar	ign[96];		/* reserved, ignored */
 };
 
-union FPsave {
-	uchar align[512+15];
-	Fxsave;
+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
 {
 	uintptr	base;
@@ -147,16 +140,6 @@
 	
 	u64int	dr[8];
 	void	*vmx;
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave
-{
-	ulong	svflags;
-	ulong	svcs;
-	ulong	svss;
 };
 
 #include "../port/portdat.h"
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -392,15 +392,13 @@
  * SIMD Floating Point.
  * Assembler support to get at the individual instructions
  * 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 _fldcw(u16int);
 extern void _fnclex(void);
 extern void _fninit(void);
-extern void _fxrstor(Fxsave*);
-extern void _fxsave(Fxsave*);
+extern void _fxrstor(void*);
+extern void _fxsave(void*);
 extern void _fwait(void);
 extern void _ldmxcsr(u32int);
 extern void _stts(void);
@@ -418,24 +416,16 @@
 }
 
 void
-fpssesave(FPsave *fps)
+fpssesave(FPsave *s)
 {
-	Fxsave *fx = (Fxsave*)ROUND(((uintptr)fps), FPalign);
-
-	_fxsave(fx);
+	_fxsave(s);
 	_stts();
-	if(fx != (Fxsave*)fps)
-		memmove((Fxsave*)fps, fx, sizeof(Fxsave));
 }
 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();
-	_fxrstor(fx);
+	_fxrstor(s);
 }
 
 static char* mathmsg[] =
@@ -488,9 +478,9 @@
 	/*
 	 * Save FPU state to check out the error.
 	 */
-	fpsave(&up->fpsave);
+	fpsave(up->fpsave);
 	up->fpstate = FPinactive;
-	mathnote(up->fpsave.fsw, up->fpsave.rip);
+	mathnote(up->fpsave->fsw, up->fpsave->rip);
 }
 
 /*
@@ -499,9 +489,9 @@
 static void
 simderror(Ureg *ureg, void*)
 {
-	fpsave(&up->fpsave);
+	fpsave(up->fpsave);
 	up->fpstate = FPinactive;
-	mathnote(up->fpsave.mxcsr & 0x3f, ureg->pc);
+	mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc);
 }
 
 void
@@ -538,6 +528,8 @@
 	switch(up->fpstate){
 	case FPinit:
 		fpinit();
+		while(up->fpsave == nil)
+			up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
 		up->fpstate = FPactive;
 		break;
 	case FPinactive:
@@ -548,13 +540,13 @@
 		 * More attention should probably be paid here to the
 		 * exception masks and error summary.
 		 */
-		status = up->fpsave.fsw;
-		control = up->fpsave.fcw;
+		status = up->fpsave->fsw;
+		control = up->fpsave->fcw;
 		if((status & ~control) & 0x07F){
-			mathnote(status, up->fpsave.rip);
+			mathnote(status, up->fpsave->rip);
 			break;
 		}
-		fprestore(&up->fpsave);
+		fprestore(up->fpsave);
 		up->fpstate = FPactive;
 		break;
 	case FPactive:
@@ -605,10 +597,12 @@
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = 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;
 	}
 	splx(s);
@@ -665,7 +659,7 @@
 			 * until the process runs again and generates an
 			 * emulation fault to activate the FPU.
 			 */
-			fpsave(&p->fpsave);
+			fpsave(p->fpsave);
 		}
 		p->fpstate = FPinactive;
 	}
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -823,7 +823,7 @@
 		return 0;
 
 	if(up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -1012,7 +1012,9 @@
 		goto regread;
 
 	case Qfpregs:
-		rptr = (uchar*)&p->fpsave;
+		if(p->fpstate != FPinactive)
+			error(Enoreg);
+		rptr = (uchar*)p->fpsave;
 		rsize = sizeof(FPsave);
 	regread:
 		if(rptr == nil)
@@ -1232,7 +1234,9 @@
 			n = 0;
 		else if(offset+n > sizeof(FPsave))
 			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;
 
 	case Qctl:
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -676,6 +676,8 @@
 	Fgrp	*closingfgrp;	/* used during teardown */
 
 	ulong	parentpid;
+
+	int	insyscall;
 	ulong	time[6];	/* User, Sys, Real; child U, S, R */
 
 	uvlong	kentry;		/* Kernel entry time stamp (for profiling) */
@@ -689,9 +691,6 @@
 	 */
 	vlong	pcycles;
 
-	int	insyscall;
-	int	fpstate;
-
 	QLock	debug;		/* to access debugging elements of User */
 	Proc	*pdbg;		/* the debugging process */
 	ulong	procmode;	/* proc device default file mode */
@@ -720,9 +719,8 @@
 	void	(*kpfun)(void*);
 	void	*kparg;
 
-	FPsave	fpsave;		/* address of this is known by db */
-	int	scallnr;	/* sys call number - known by db */
-	Sargs	s;		/* address of this is known by db */
+	int	scallnr;	/* sys call number */
+	Sargs	s;		/* syscall arguments */
 	int	nerrlab;
 	Label	errlab[NERR];
 	char	*syserrstr;	/* last error from a system call, errbuf0 or 1 */
@@ -766,17 +764,14 @@
 
 	void	*ureg;		/* User registers for notes */
 	void	*dbgreg;	/* User registers for devproc */
-	Notsave;
 
-	/*
-	 *  machine specific MMU
-	 */
-	PMMU;
+	PFPU;			/* machine specific fpu state */
+	PMMU;			/* machine specific mmu state */
 
 	char	*syscalltrace;	/* syscall trace */
 	
-	Watchpt	*watchpt; /* watchpoints */
-	int nwatchpt;
+	Watchpt	*watchpt;	/* watchpoints */
+	int	nwatchpt;
 };
 
 enum
--- a/sys/src/9/ppc/dat.h
+++ b/sys/src/9/ppc/dat.h
@@ -1,11 +1,12 @@
 typedef struct Conf	Conf;
+typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Imap	Imap;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct PCArch	PCArch;
 typedef struct PMMU	PMMU;
 typedef struct Page	Page;
@@ -14,6 +15,7 @@
 typedef struct Sys	Sys;
 typedef struct Ureg	Ureg;
 typedef struct Vctl	Vctl;
+typedef long		Tval;
 
 #pragma incomplete Ureg
 #pragma incomplete Imap
@@ -46,19 +48,6 @@
 };
 
 /*
- * 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
  */
 struct FPsave
@@ -73,15 +62,36 @@
 	};
 };
 
+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
 {
 	ulong	nmach;		/* processors */
 	ulong	nproc;		/* processes */
-	ulong	npage0;		/* total physical pages of memory */
-	ulong	npage1;		/* total physical pages of memory */
+	Confmem	mem[2];
 	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	nimage;		/* number of page cache image headers */
 	ulong	nswap;		/* number of swap pages */
@@ -100,14 +110,6 @@
 {
 	int	mmupid;
 	Ureg	*mmureg;		/* pointer to ureg structure */
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave
-{
-	ulong	UNUSED;
 };
 
 #include "../port/portdat.h"
--- a/sys/src/9/ppc/main.c
+++ b/sys/src/9/ppc/main.c
@@ -292,7 +292,7 @@
 	p->kentry -= t;
 	if(p->fpstate == FPactive){
 		if(p->state != Moribund)
-			fpsave(&up->fpsave);
+			fpsave(up->fpsave);
 		p->fpstate = FPinactive;
 	}
 }
--- a/sys/src/9/ppc/mkfile
+++ b/sys/src/9/ppc/mkfile
@@ -101,6 +101,6 @@
 	$AS init9.s
 	$LD -l -s -R4 -o init.out init9.$O initcode.$O /power/lib/libc.a
 	{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'
 	 echo '};'} > init.h
--- a/sys/src/9/ppc/trap.c
+++ b/sys/src/9/ppc/trap.c
@@ -243,7 +243,7 @@
 			up->fpstate = FPactive;
 			break;
 		case FPinactive:
-			fprestore(&up->fpsave);
+			fprestore(up->fpsave);
 			up->fpstate = FPactive;
 			break;
 		case FPactive:
@@ -711,7 +711,7 @@
 		return 0;
 
 	if(up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
--- a/sys/src/9/sgi/dat.h
+++ b/sys/src/9/sgi/dat.h
@@ -1,6 +1,7 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct KMap	KMap;
 typedef struct Lance	Lance;
 typedef struct Lancemem	Lancemem;
@@ -8,7 +9,6 @@
 typedef struct Lock	Lock;
 typedef struct Mach	Mach;
 typedef struct MMU	MMU;
-typedef struct Notsave	Notsave;
 typedef struct PMMU	PMMU;
 typedef struct Softtlb	Softtlb;
 typedef struct Ureg	Ureg;
@@ -73,18 +73,6 @@
 /*
  * floating point registers
  */
-enum
-{
-	/* floating point state */
-	FPinit,
-	FPactive,
-	FPinactive,
-	FPemu,
-
-	/* bit meaning floating point illegal */
-	FPillegal= 0x100,
-};
-
 enum {
 	Nfpregs		= 32,		/* floats; half as many doubles */
 };
@@ -111,20 +99,30 @@
 	int	fpcnt;			/* how many consecutive at that addr */
 };
 
-/*
- *  mmu goo in the Proc structure
- */
-struct PMMU
+struct PFPU
 {
-	int	pidonmach[MAXMACH];
+	int	fpstate;
+	FPsave	fpsave[1];
 };
 
+enum
+{
+	/* floating point state */
+	FPinit,
+	FPactive,
+	FPinactive,
+	FPemu,
+
+	/* bit meaning floating point illegal */
+	FPillegal= 0x100,
+};
+
 /*
- *  things saved in the Proc structure during a notify
+ *  mmu goo in the Proc structure
  */
-struct Notsave
+struct PMMU
 {
-	ulong	nonempty;
+	int	pidonmach[MAXMACH];
 };
 
 #include "../port/portdat.h"
--- a/sys/src/9/sgi/fptrap.c
+++ b/sys/src/9/sgi/fptrap.c
@@ -29,7 +29,7 @@
 {
 	ulong iw, npc;
 
-	if((up->fpsave.fpstatus&(1<<17)) == 0)
+	if((up->fpsave->fpstatus&(1<<17)) == 0)
 		return;
 
 	if(ur->cause & (1<<31))
@@ -41,7 +41,7 @@
 		return;
 
 	if(ur->cause & (1<<31)){
-		npc = branch(ur, up->fpsave.fpstatus);
+		npc = branch(ur, up->fpsave->fpstatus);
 		if(npc == 0)
 			return;
 		ur->pc = npc;
@@ -49,7 +49,7 @@
 	else
 		ur->pc += 4;
 
-	up->fpsave.fpstatus &= ~(1<<17);
+	up->fpsave->fpstatus &= ~(1<<17);
 }
 
 static void
@@ -107,8 +107,8 @@
 	ft = (iw>>16) & ((1<<5)-1);
 	fs = (iw>>11) & ((1<<5)-1);
 	fd = (iw>>6) & ((1<<5)-1);
-	unpack(&up->fpsave, fmt, fs, &ss, &es);
-	unpack(&up->fpsave, fmt, ft, &st, &et);
+	unpack(up->fpsave, fmt, fs, &ss, &es);
+	unpack(up->fpsave, fmt, ft, &st, &et);
 	ed = 0;
 	maxe = 0;
 	maxm = 0;
@@ -124,11 +124,11 @@
 	}
 	switch(op){
 	case ABS:
-		up->fpsave.reg[fd] &= ~0x80000000;
+		up->fpsave->reg[fd] &= ~0x80000000;
 		return 1;
 
 	case NEG:
-		up->fpsave.reg[fd] ^= 0x80000000;
+		up->fpsave->reg[fd] ^= 0x80000000;
 		return 1;
 
 	case SUB:
@@ -164,9 +164,9 @@
 		return 0;
 	}
 	if(ed <= -(maxe-5)){	/* guess: underflow */
-		zeroreg(&up->fpsave, fmt, fd, sd);
+		zeroreg(up->fpsave, fmt, fd, sd);
 		/* Set underflow exception and sticky */
-		up->fpsave.fpstatus |= (1<<3)|(1<<13);
+		up->fpsave->fpstatus |= (1<<3)|(1<<13);
 		return 1;
 	}
 	return 0;
--- a/sys/src/9/sgi/main.c
+++ b/sys/src/9/sgi/main.c
@@ -396,7 +396,7 @@
 procsetup(Proc *p)
 {
 	p->fpstate = FPinit;
-	p->fpsave = initfp;
+	memmove(p->fpsave, &initfp, sizeof(FPsave));
 
 	cycles(&p->kentry);
 	p->pcycles = -p->kentry;
@@ -413,11 +413,11 @@
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
-		savefpregs(&up->fpsave);
+		savefpregs(up->fpsave);
 		up->fpstate = FPinactive;
 		/* wet floor */
 	case FPinactive:
-		p->fpsave = up->fpsave;
+		memmove(p->fpsave, up->fpsave, sizeof(FPsave));
 		p->fpstate = FPinactive;
 	}
 	splx(s);
@@ -430,7 +430,7 @@
 
 	if(p->fpstate == FPactive){
 		if(p->state != Moribund) {
-			savefpregs(&p->fpsave);
+			savefpregs(p->fpsave);
 			p->fpstate = FPinactive;
 		}
 	}
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -212,7 +212,7 @@
 		if(!user)
 			goto Default;
 		if(up->fpstate == FPactive){
-			savefpregs(&up->fpsave);
+			savefpregs(up->fpsave);
 			up->fpstate = FPinactive;
 		}
 		clrfpintr();
@@ -257,7 +257,7 @@
 				break;
 			}
 			if(up->fpstate == FPinit || up->fpstate == FPinactive){
-				restfpregs(&up->fpsave, up->fpsave.fpstatus&~FPEXPMASK);
+				restfpregs(up->fpsave, up->fpsave->fpstatus&~FPEXPMASK);
 				up->fpstate = FPactive;
 				ur->status |= CU1;
 				break;
@@ -289,7 +289,7 @@
 	}
 
 	if(fpchk) {
-		fpfcr31 = up->fpsave.fpstatus;
+		fpfcr31 = up->fpsave->fpstatus;
 		if((fpfcr31>>12) & ((fpfcr31>>7)|0x20) & 0x3f) {
 			spllo();
 			fpexcep	= fpexcname(ur, fpfcr31, buf1, sizeof buf1);
@@ -501,7 +501,7 @@
 		return 0;
 
 	if(up->fpstate == FPactive){
-		savefpregs(&up->fpsave);
+		savefpregs(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
--- a/sys/src/9/teg2/dat.h
+++ b/sys/src/9/teg2/dat.h
@@ -24,6 +24,7 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct ISAConf	ISAConf;
 typedef struct Isolated Isolated;
 typedef struct Label	Label;
@@ -33,7 +34,6 @@
 typedef struct MMMU	MMMU;
 typedef struct Mach	Mach;
 typedef u32int Mreg;				/* Msr - bloody UART */
-typedef struct Notsave	Notsave;
 typedef struct Page	Page;
 typedef struct Pcisiz Pcisiz;
 typedef struct Pcidev Pcidev;
@@ -72,14 +72,14 @@
 	uintptr	pc;
 };
 
+/*
+ * emulated or vfp3 floating point
+ */
 enum {
 	Maxfpregs	= 32,	/* could be 16 or 32, see Mach.fpnregs */
 	Nfpctlregs	= 16,
 };
 
-/*
- * emulated or vfp3 floating point
- */
 struct FPsave
 {
 	ulong	status;
@@ -94,9 +94,12 @@
 	uintptr	pc;		/* of failed fp instr. */
 };
 
-/*
- * FPsave.fpstate
- */
+struct PFPU
+{
+	int	fpstate;
+	FPsave	fpsave[1];
+};
+
 enum
 {
 	FPinit,
@@ -133,13 +136,6 @@
 	ulong	hz;		/* processor cycle freq */
 	ulong	mhz;
 	int	monitor;	/* flag */
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
 };
 
 /*
--- a/sys/src/9/teg2/fpiarm.c
+++ b/sys/src/9/teg2/fpiarm.c
@@ -650,7 +650,7 @@
 
 	if(up == nil)
 		panic("fpiarm not in a process");
-	ufp = &up->fpsave;
+	ufp = up->fpsave;
 	/*
 	 * because all the emulated fp state is in the proc structure,
 	 * it need not be saved/restored
--- a/sys/src/9/xen/main.c
+++ b/sys/src/9/xen/main.c
@@ -450,7 +450,7 @@
 	ulong status;
 	char *msg, note[ERRMAX];
 
-	status = up->fpsave.status;
+	status = up->fpsave->status;
 
 	/*
 	 * Some attention should probably be paid here to the
@@ -473,7 +473,7 @@
 			msg = "invalid operation";
 	}
  	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);
 }
 
@@ -493,12 +493,12 @@
 	/*
 	 *  save floating point state to check out error
 	 */
-	fpenv(&up->fpsave);
+	fpenv(up->fpsave);
 	mathnote();
 
 	if(ur->pc & KZERO)
 		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 @@
 	switch(up->fpstate){
 	case FPinit:
 		fpinit();
+		while(up->fpsave == nil)
+			up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
 		up->fpstate = FPactive;
 		break;
 	case FPinactive:
@@ -525,11 +527,11 @@
 		 * More attention should probably be paid here to the
 		 * exception masks and error summary.
 		 */
-		if((up->fpsave.status & ~up->fpsave.control) & 0x07F){
+		if((up->fpsave->status & ~up->fpsave->control) & 0x07F){
 			mathnote();
 			break;
 		}
-		fprestore(&up->fpsave);
+		fprestore(up->fpsave);
 		up->fpstate = FPactive;
 		break;
 	case FPactive:
@@ -580,10 +582,12 @@
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = 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;
 	}
 	splx(s);
@@ -622,7 +626,7 @@
 			 * until the process runs again and generates an
 			 * emulation fault to activate the FPU.
 			 */
-			fpsave(&p->fpsave);
+			fpsave(p->fpsave);
 		}
 		p->fpstate = FPinactive;
 	}
--- a/sys/src/9/xen/trap.c
+++ b/sys/src/9/xen/trap.c
@@ -674,7 +674,7 @@
 	scallnr = ureg->ax;
 	up->scallnr = scallnr;
 	if(scallnr == RFORK && up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	spllo();
@@ -764,7 +764,7 @@
 		return 0;
 
 	if(up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
--- a/sys/src/9/zynq/dat.h
+++ b/sys/src/9/zynq/dat.h
@@ -1,6 +1,7 @@
 typedef struct Conf	Conf;
 typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
+typedef struct PFPU	PFPU;
 typedef struct L1	L1;
 typedef struct Label	Label;
 typedef struct Lock	Lock;
@@ -7,7 +8,6 @@
 typedef struct KMap	KMap;
 typedef struct MMMU	MMMU;
 typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
 typedef struct Page	Page;
 typedef struct Proc	Proc;
 typedef struct PMMU	PMMU;
@@ -43,9 +43,12 @@
 	uchar	regs[256];
 };
 
-/*
- * FPsave.status
- */
+struct PFPU
+{
+	int	fpstate;
+	FPsave	fpsave[1];
+};
+
 enum
 {
 	FPinit,
@@ -77,13 +80,6 @@
 	ulong	nswap;		/* number of swap pages */
 	int	nswppo;		/* max # of pageouts per segment pass */
 	int	monitor;
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
 };
 
 /*
--- a/sys/src/9/zynq/main.c
+++ b/sys/src/9/zynq/main.c
@@ -50,10 +50,10 @@
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	case FPinactive:
-		p->fpsave = up->fpsave;
+		memmove(p->fpsave, up->fpsave, sizeof(FPsave));
 		p->fpstate = FPinactive;
 	}
 	splx(s);
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -134,7 +134,7 @@
 		break;
 	case FPinactive:
 		s = splhi();
-		fprestore(&up->fpsave);
+		fprestore(up->fpsave);
 		up->fpstate = FPactive;
 		splx(s);
 		break;
@@ -304,7 +304,7 @@
 		return 0;
 
 	if(up->fpstate == FPactive){
-		fpsave(&up->fpsave);
+		fpsave(up->fpsave);
 		up->fpstate = FPinactive;
 	}
 	up->fpstate |= FPillegal;
@@ -517,7 +517,7 @@
 		if(p->state == Moribund)
 			fpclear();
 		else
-			fpsave(&p->fpsave);
+			fpsave(p->fpsave);
 		p->fpstate = FPinactive;
 	}
 	cycles(&t);