Module Name:    src
Committed By:   matt
Date:           Tue Jun  7 00:48:32 UTC 2011

Modified Files:
        src/sys/arch/alpha/alpha: compat_13_machdep.c compat_16_machdep.c
            core_machdep.c cpu.c fp_complete.c genassym.cf ipifuncs.c locore.s
            machdep.c process_machdep.c trap.c vm_machdep.c
        src/sys/arch/alpha/include: alpha.h intr.h pcb.h proc.h types.h
        src/sys/arch/mips/mips: mips_machdep.c
        src/sys/arch/powerpc/powerpc: fpu.c powerpc_machdep.c

Log Message:
Switch alpha to use PCU to manage the FPU.
Tested by mhitch and review by rmind.


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/alpha/alpha/compat_13_machdep.c
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/alpha/alpha/compat_16_machdep.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/alpha/alpha/core_machdep.c
cvs rdiff -u -r1.90 -r1.91 src/sys/arch/alpha/alpha/cpu.c
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/alpha/alpha/fp_complete.c
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/alpha/alpha/genassym.cf
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/alpha/alpha/ipifuncs.c
cvs rdiff -u -r1.120 -r1.121 src/sys/arch/alpha/alpha/locore.s
cvs rdiff -u -r1.333 -r1.334 src/sys/arch/alpha/alpha/machdep.c
cvs rdiff -u -r1.25 -r1.26 src/sys/arch/alpha/alpha/process_machdep.c
cvs rdiff -u -r1.125 -r1.126 src/sys/arch/alpha/alpha/trap.c
cvs rdiff -u -r1.106 -r1.107 src/sys/arch/alpha/alpha/vm_machdep.c
cvs rdiff -u -r1.25 -r1.26 src/sys/arch/alpha/include/alpha.h
cvs rdiff -u -r1.68 -r1.69 src/sys/arch/alpha/include/intr.h
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/alpha/include/pcb.h \
    src/sys/arch/alpha/include/proc.h
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/alpha/include/types.h
cvs rdiff -u -r1.240 -r1.241 src/sys/arch/mips/mips/mips_machdep.c
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/powerpc/powerpc/fpu.c
cvs rdiff -u -r1.49 -r1.50 src/sys/arch/powerpc/powerpc/powerpc_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/alpha/alpha/compat_13_machdep.c
diff -u src/sys/arch/alpha/alpha/compat_13_machdep.c:1.18 src/sys/arch/alpha/alpha/compat_13_machdep.c:1.19
--- src/sys/arch/alpha/alpha/compat_13_machdep.c:1.18	Sat Nov 21 05:35:40 2009
+++ src/sys/arch/alpha/alpha/compat_13_machdep.c	Tue Jun  7 00:48:29 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: compat_13_machdep.c,v 1.18 2009/11/21 05:35:40 rmind Exp $ */
+/* $NetBSD: compat_13_machdep.c,v 1.19 2011/06/07 00:48:29 matt Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: compat_13_machdep.c,v 1.18 2009/11/21 05:35:40 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: compat_13_machdep.c,v 1.19 2011/06/07 00:48:29 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -94,8 +94,7 @@
 
 	/* XXX ksc.sc_ownedfp ? */
 	pcb = lwp_getpcb(l);
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 0);
+	fpu_discard();
 	memcpy(&pcb->pcb_fp, (struct fpreg *)ksc.sc_fpregs,
 	    sizeof(struct fpreg));
 	/* XXX ksc.sc_fp_control ? */

Index: src/sys/arch/alpha/alpha/compat_16_machdep.c
diff -u src/sys/arch/alpha/alpha/compat_16_machdep.c:1.16 src/sys/arch/alpha/alpha/compat_16_machdep.c:1.17
--- src/sys/arch/alpha/alpha/compat_16_machdep.c:1.16	Sat Nov 21 05:35:40 2009
+++ src/sys/arch/alpha/alpha/compat_16_machdep.c	Tue Jun  7 00:48:29 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: compat_16_machdep.c,v 1.16 2009/11/21 05:35:40 rmind Exp $ */
+/* $NetBSD: compat_16_machdep.c,v 1.17 2011/06/07 00:48:29 matt Exp $ */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -86,7 +86,7 @@
 #include <machine/cpu.h>
 #include <machine/reg.h>
 
-__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.16 2009/11/21 05:35:40 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.17 2011/06/07 00:48:29 matt Exp $");
 
 
 #ifdef DEBUG
@@ -132,9 +132,8 @@
 	frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();
 
  	/* save the floating-point state, if necessary, then copy it. */
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 1);
-	frame.sf_sc.sc_ownedfp = l->l_md.md_flags & MDP_FPUSED;
+	fpu_save();
+	frame.sf_sc.sc_ownedfp = fpu_used_p(l);
 	memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &pcb->pcb_fp,
 	    sizeof(struct fpreg));
 	frame.sf_sc.sc_fp_control = alpha_read_fp_c(l);
@@ -281,14 +280,13 @@
 	regtoframe((struct reg *)ksc.sc_regs, l->l_md.md_tf);
 	alpha_pal_wrusp(ksc.sc_regs[R_SP]);
 
-	/* XXX ksc.sc_ownedfp ? */
 	pcb = lwp_getpcb(l);
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 0);
+	fpu_discard();
 	memcpy(&pcb->pcb_fp, (struct fpreg *)ksc.sc_fpregs,
 	    sizeof(struct fpreg));
 	pcb->pcb_fp.fpr_cr = ksc.sc_fpcr;
-	l->l_md.md_flags = ksc.sc_fp_control & MDP_FP_C;
+	l->l_md.md_flags = (ksc.sc_fp_control & MDLWP_FP_C)
+	    | (ksc.sc_ownedfp ? MDLWP_FPUSED : 0);
 
 	mutex_enter(p->p_lock);
 	/* Restore signal stack. */

Index: src/sys/arch/alpha/alpha/core_machdep.c
diff -u src/sys/arch/alpha/alpha/core_machdep.c:1.4 src/sys/arch/alpha/alpha/core_machdep.c:1.5
--- src/sys/arch/alpha/alpha/core_machdep.c:1.4	Wed Dec 15 01:32:31 2010
+++ src/sys/arch/alpha/alpha/core_machdep.c	Tue Jun  7 00:48:29 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: core_machdep.c,v 1.4 2010/12/15 01:32:31 matt Exp $ */
+/* $NetBSD: core_machdep.c,v 1.5 2011/06/07 00:48:29 matt Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: core_machdep.c,v 1.4 2010/12/15 01:32:31 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: core_machdep.c,v 1.5 2011/06/07 00:48:29 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -68,10 +68,9 @@
 
 	cpustate.md_tf = *l->l_md.md_tf;
 	cpustate.md_tf.tf_regs[FRAME_SP] = alpha_pal_rdusp();	/* XXX */
-	if (l->l_md.md_flags & MDP_FPUSED) {
+	if (fpu_used_p(l)) {
 		struct pcb *pcb = lwp_getpcb(l);
-		if (pcb->pcb_fpcpu != NULL)
-			fpusave_proc(l, 1);
+		fpu_save();
 		cpustate.md_fpstate = pcb->pcb_fp;
 	} else
 		memset(&cpustate.md_fpstate, 0, sizeof(cpustate.md_fpstate));

Index: src/sys/arch/alpha/alpha/cpu.c
diff -u src/sys/arch/alpha/alpha/cpu.c:1.90 src/sys/arch/alpha/alpha/cpu.c:1.91
--- src/sys/arch/alpha/alpha/cpu.c:1.90	Fri Dec 17 02:36:35 2010
+++ src/sys/arch/alpha/alpha/cpu.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.90 2010/12/17 02:36:35 joerg Exp $ */
+/* $NetBSD: cpu.c,v 1.91 2011/06/07 00:48:30 matt Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.90 2010/12/17 02:36:35 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.91 2011/06/07 00:48:30 matt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -660,16 +660,15 @@
 	struct cpu_info *ci;
 	CPU_INFO_ITERATOR cii;
 
-	db_printf("addr		dev	id	flags	ipis	curproc		fpcurproc\n");
+	db_printf("addr		dev	id	flags	ipis	curproc\n");
 	for (CPU_INFO_FOREACH(cii, ci)) {
-		db_printf("%p	%s	%lu	%lx	%lx	%p	%p\n",
+		db_printf("%p	%s	%lu	%lx	%lx	%p\n",
 		    ci,
 		    ci->ci_softc->sc_dev.dv_xname,
 		    ci->ci_cpuid,
 		    ci->ci_flags,
 		    ci->ci_ipis,
-		    ci->ci_curlwp,
-		    ci->ci_fpcurlwp);
+		    ci->ci_curlwp);
 	}
 }
 

Index: src/sys/arch/alpha/alpha/fp_complete.c
diff -u src/sys/arch/alpha/alpha/fp_complete.c:1.12 src/sys/arch/alpha/alpha/fp_complete.c:1.13
--- src/sys/arch/alpha/alpha/fp_complete.c:1.12	Sat May 10 15:31:04 2008
+++ src/sys/arch/alpha/alpha/fp_complete.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: fp_complete.c,v 1.12 2008/05/10 15:31:04 martin Exp $ */
+/* $NetBSD: fp_complete.c,v 1.13 2011/06/07 00:48:30 matt Exp $ */
 
 /*-
  * Copyright (c) 2001 Ross Harvey
@@ -35,13 +35,15 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.12 2008/05/10 15:31:04 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.13 2011/06/07 00:48:30 matt Exp $");
 
 #include "opt_compat_osf1.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/atomic.h>
+#include <sys/evcnt.h>
 
 #ifdef COMPAT_OSF1
 #include <compat/osf1/osf1_exec.h>
@@ -99,6 +101,9 @@
 
 #define	CRBLIT(sw, hw, m, offs) (((sw) & ~(m)) | ((hw) >> (offs) & (m)))
 
+struct evcnt fpevent_use;
+struct evcnt fpevent_reuse;
+
 /*
  * Temporary trap shadow instrumentation. The [un]resolved counters
  * could be kept permanently, as they provide information on whether
@@ -398,12 +403,13 @@
 {
 	u_int64_t md_flags;
 
-	fp_c &= MDP_FP_C;
+	fp_c &= MDLWP_FP_C;
 	md_flags = l->l_md.md_flags;
-	if ((md_flags & MDP_FP_C) == fp_c)
+	if ((md_flags & MDLWP_FP_C) == fp_c)
 		return;
-	l->l_md.md_flags = (md_flags & ~MDP_FP_C) | fp_c;
-	alpha_enable_fp(l, 1);
+	l->l_md.md_flags = (md_flags & ~MDLWP_FP_C) | fp_c;
+	fpu_load();
+	alpha_pal_wrfen(1);
 	fp_c_to_fpcr(l);
 	alpha_pal_wrfen(0);
 }
@@ -417,7 +423,7 @@
 	 * but in a transparent way. Some of the code for that would need to
 	 * go right here.
 	 */
-	return l->l_md.md_flags & MDP_FP_C;
+	return l->l_md.md_flags & MDLWP_FP_C;
 }
 
 static float64
@@ -579,7 +585,8 @@
 		this_cannot_happen(6, -1);
 		return SIGSEGV;
 	}
-	alpha_enable_fp(l, 1);
+	fpu_load();
+	alpha_pal_wrfen(1);
 	/*
 	 * If necessary, lie about the dynamic rounding mode so emulation
 	 * software need go to only one place for it, and so we don't have to
@@ -707,3 +714,55 @@
 	}
 	return 0;
 }
+
+/*
+ * Load the float-point context for the current lwp.
+ */
+void
+fpu_state_load(struct lwp *l, bool used)
+{
+	struct pcb * const pcb = lwp_getpcb(l);
+
+	/*
+	 * Instrument FP usage -- if a process had not previously
+	 * used FP, mark it as having used FP for the first time,
+	 * and count this event.
+	 *
+	 * If a process has used FP, count a "used FP, and took
+	 * a trap to use it again" event.
+	 */
+	if (!fpu_used_p(l)) {
+		atomic_inc_ulong(&fpevent_use.ev_count);
+		fpu_mark_used(l);
+	} else
+		atomic_inc_ulong(&fpevent_reuse.ev_count);
+
+	alpha_pal_wrfen(1);
+	restorefpstate(&pcb->pcb_fp);
+	alpha_pal_wrfen(0);
+
+	l->l_md.md_flags |= MDLWP_FPACTIVE;
+}
+
+/*
+ * Save the FPU state.
+ */
+
+void
+fpu_state_save(struct lwp *l)
+{
+	struct pcb * const pcb = lwp_getpcb(l);
+
+	alpha_pal_wrfen(1);
+	savefpstate(&pcb->pcb_fp);
+	alpha_pal_wrfen(0);
+}
+
+/*
+ * Release the FPU.
+ */
+void
+fpu_state_release(struct lwp *l)
+{
+	l->l_md.md_flags &= ~MDLWP_FPACTIVE;
+}

Index: src/sys/arch/alpha/alpha/genassym.cf
diff -u src/sys/arch/alpha/alpha/genassym.cf:1.19 src/sys/arch/alpha/alpha/genassym.cf:1.20
--- src/sys/arch/alpha/alpha/genassym.cf:1.19	Wed Dec 15 01:33:37 2010
+++ src/sys/arch/alpha/alpha/genassym.cf	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-# $NetBSD: genassym.cf,v 1.19 2010/12/15 01:33:37 matt Exp $
+# $NetBSD: genassym.cf,v 1.20 2011/06/07 00:48:30 matt Exp $
 
 #
 # Copyright (c) 1982, 1990, 1993
@@ -190,7 +190,6 @@
 
 # CPU info
 define	CPU_INFO_CURLWP		offsetof(struct cpu_info, ci_curlwp)
-define	CPU_INFO_FPCURLWP	offsetof(struct cpu_info, ci_fpcurlwp)
 define	CPU_INFO_CURPCB		offsetof(struct cpu_info, ci_curpcb)
 define	CPU_INFO_IDLE_LWP	offsetof(struct cpu_info, ci_data.cpu_idlelwp)
 define	CPU_INFO_SIZEOF		sizeof(struct cpu_info)

Index: src/sys/arch/alpha/alpha/ipifuncs.c
diff -u src/sys/arch/alpha/alpha/ipifuncs.c:1.45 src/sys/arch/alpha/alpha/ipifuncs.c:1.46
--- src/sys/arch/alpha/alpha/ipifuncs.c:1.45	Fri Dec 17 02:36:35 2010
+++ src/sys/arch/alpha/alpha/ipifuncs.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: ipifuncs.c,v 1.45 2010/12/17 02:36:35 joerg Exp $ */
+/* $NetBSD: ipifuncs.c,v 1.46 2011/06/07 00:48:30 matt Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.45 2010/12/17 02:36:35 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.46 2011/06/07 00:48:30 matt Exp $");
 
 /*
  * Interprocessor interrupt handlers.
@@ -47,6 +47,7 @@
 #include <sys/cpu.h>
 #include <sys/intr.h>
 #include <sys/xcall.h>
+#include <sys/bitops.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -62,8 +63,6 @@
 void	alpha_ipi_microset(struct cpu_info *, struct trapframe *);
 void	alpha_ipi_imb(struct cpu_info *, struct trapframe *);
 void	alpha_ipi_ast(struct cpu_info *, struct trapframe *);
-void	alpha_ipi_synch_fpu(struct cpu_info *, struct trapframe *);
-void	alpha_ipi_discard_fpu(struct cpu_info *, struct trapframe *);
 void	alpha_ipi_pause(struct cpu_info *, struct trapframe *);
 void	alpha_ipi_xcall(struct cpu_info *, struct trapframe *);
 
@@ -71,28 +70,24 @@
  * NOTE: This table must be kept in order with the bit definitions
  * in <machine/intr.h>.
  */
-ipifunc_t ipifuncs[ALPHA_NIPIS] = {
-	alpha_ipi_halt,
-	alpha_ipi_microset,
-	pmap_do_tlb_shootdown,
-	alpha_ipi_imb,
-	alpha_ipi_ast,
-	alpha_ipi_synch_fpu,
-	alpha_ipi_discard_fpu,
-	alpha_ipi_pause,
-	alpha_ipi_xcall
+const ipifunc_t ipifuncs[ALPHA_NIPIS] = {
+	[ilog2(ALPHA_IPI_HALT)] =	alpha_ipi_halt,
+	[ilog2(ALPHA_IPI_MICROSET)] =	alpha_ipi_microset,
+	[ilog2(ALPHA_IPI_SHOOTDOWN)] =	pmap_do_tlb_shootdown,
+	[ilog2(ALPHA_IPI_IMB)] =	alpha_ipi_imb,
+	[ilog2(ALPHA_IPI_AST)] =	alpha_ipi_ast,
+	[ilog2(ALPHA_IPI_PAUSE)] =	alpha_ipi_pause,
+	[ilog2(ALPHA_IPI_XCALL)] =	alpha_ipi_xcall
 };
 
-const char *ipinames[ALPHA_NIPIS] = {
-	"halt ipi",
-	"microset ipi",
-	"shootdown ipi",
-	"imb ipi",
-	"ast ipi",
-	"synch fpu ipi",
-	"discard fpu ipi",
-	"pause ipi",
-	"xcall ipi"
+const char * const ipinames[ALPHA_NIPIS] = {
+	[ilog2(ALPHA_IPI_HALT)] =	"halt ipi",
+	[ilog2(ALPHA_IPI_MICROSET)] =	"microset ipi",
+	[ilog2(ALPHA_IPI_SHOOTDOWN)] =	"shootdown ipi",
+	[ilog2(ALPHA_IPI_IMB)] =	"imb ipi",
+	[ilog2(ALPHA_IPI_AST)] =	"ast ipi",
+	[ilog2(ALPHA_IPI_PAUSE)] =	"pause ipi",
+	[ilog2(ALPHA_IPI_XCALL)] =	"xcall ipi"
 };
 
 /*
@@ -269,24 +264,6 @@
 }
 
 void
-alpha_ipi_synch_fpu(struct cpu_info *ci, struct trapframe *framep)
-{
-
-	if (ci->ci_flags & CPUF_FPUSAVE)
-		return;
-	fpusave_cpu(ci, 1);
-}
-
-void
-alpha_ipi_discard_fpu(struct cpu_info *ci, struct trapframe *framep)
-{
-
-	if (ci->ci_flags & CPUF_FPUSAVE)
-		return;
-	fpusave_cpu(ci, 0);
-}
-
-void
 alpha_ipi_pause(struct cpu_info *ci, struct trapframe *framep)
 {
 	u_long cpumask = (1UL << ci->ci_cpuid);

Index: src/sys/arch/alpha/alpha/locore.s
diff -u src/sys/arch/alpha/alpha/locore.s:1.120 src/sys/arch/alpha/alpha/locore.s:1.121
--- src/sys/arch/alpha/alpha/locore.s:1.120	Wed Jul  7 01:17:49 2010
+++ src/sys/arch/alpha/alpha/locore.s	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.s,v 1.120 2010/07/07 01:17:49 chs Exp $ */
+/* $NetBSD: locore.s,v 1.121 2011/06/07 00:48:30 matt Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 
 #include <machine/asm.h>
 
-__KERNEL_RCSID(0, "$NetBSD: locore.s,v 1.120 2010/07/07 01:17:49 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.s,v 1.121 2011/06/07 00:48:30 matt Exp $");
 
 #include "assym.h"
 
@@ -275,11 +275,9 @@
 	bne	t3, 7f				/* yes */
 	/* no: headed back to user space */
 
-	/* Enable the FPU based on whether the current proc is fpcurlwp. */
-4:	ldq	t2, CPU_INFO_FPCURLWP(v0)
-	cmpeq	t1, t2, t1
-	mov	zero, a0
-	cmovne	t1, 1, a0
+	/* Enable the FPU based on whether MDLWP_FPACTIVE is set. */
+4:	ldq	t2, L_MD_FLAGS(t1)
+	cmplt	t2, zero, a0
 	call_pal PAL_OSF1_wrfen
 
 	/* restore the registers, and return */

Index: src/sys/arch/alpha/alpha/machdep.c
diff -u src/sys/arch/alpha/alpha/machdep.c:1.333 src/sys/arch/alpha/alpha/machdep.c:1.334
--- src/sys/arch/alpha/alpha/machdep.c:1.333	Tue May 24 20:26:34 2011
+++ src/sys/arch/alpha/alpha/machdep.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.333 2011/05/24 20:26:34 rmind Exp $ */
+/* $NetBSD: machdep.c,v 1.334 2011/06/07 00:48:30 matt Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.333 2011/05/24 20:26:34 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.334 2011/06/07 00:48:30 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -205,6 +205,17 @@
 void	identifycpu(void);
 void	printregs(struct reg *);
 
+const pcu_ops_t fpu_ops = {
+	.pcu_id = PCU_FPU,
+	.pcu_state_load = fpu_state_load,
+	.pcu_state_save = fpu_state_save,
+	.pcu_state_release = fpu_state_release,
+};
+
+const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = {
+	[PCU_FPU] = &fpu_ops,
+};
+
 void
 alpha_init(u_long pfn, u_long ptb, u_long bim, u_long bip, u_long biv)
 	/* pfn:		 first free PFN number */
@@ -657,7 +668,6 @@
 	 */
 	pcb0->pcb_hw.apcb_ksp = v + USPACE - sizeof(struct trapframe);
 	lwp0.l_md.md_tf = (struct trapframe *)pcb0->pcb_hw.apcb_ksp;
-	mutex_init(&pcb0->pcb_fpcpu_lock, MUTEX_DEFAULT, IPL_HIGH);
 
 	/* Indicate that lwp0 has a CPU. */
 	lwp0.l_cpu = ci;
@@ -1631,117 +1641,12 @@
 	tfp->tf_regs[FRAME_A3] = l->l_proc->p_psstrp;	/* a3 = ps_strings */
 	tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC];	/* a.k.a. PV */
 
-	l->l_md.md_flags &= ~MDP_FPUSED;
+	l->l_md.md_flags &= ~MDLWP_FPUSED;
 	if (__predict_true((l->l_md.md_flags & IEEE_INHERIT) == 0)) {
-		l->l_md.md_flags &= ~MDP_FP_C;
+		l->l_md.md_flags &= ~MDLWP_FP_C;
 		pcb->pcb_fp.fpr_cr = FPCR_DYN(FP_RN);
 	}
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 0);
-}
-
-/*
- * Release the FPU.
- */
-void
-fpusave_cpu(struct cpu_info *ci, int save)
-{
-	struct lwp *l;
-	struct pcb *pcb;
-#if defined(MULTIPROCESSOR)
-	int s;
-#endif
-
-	KDASSERT(ci == curcpu());
-
-#if defined(MULTIPROCESSOR)
-	s = splhigh();		/* block IPIs for the duration */
-	atomic_or_ulong(&ci->ci_flags, CPUF_FPUSAVE);
-#endif
-
-	l = ci->ci_fpcurlwp;
-	if (l == NULL)
-		goto out;
-
-	pcb = lwp_getpcb(l);
-	if (save) {
-		alpha_pal_wrfen(1);
-		savefpstate(&pcb->pcb_fp);
-	}
-
-	alpha_pal_wrfen(0);
-
-	FPCPU_LOCK(pcb);
-
-	pcb->pcb_fpcpu = NULL;
-	ci->ci_fpcurlwp = NULL;
-
-	FPCPU_UNLOCK(pcb);
-
- out:
-#if defined(MULTIPROCESSOR)
-	atomic_and_ulong(&ci->ci_flags, ~CPUF_FPUSAVE);
-	splx(s);
-#endif
-	return;
-}
-
-/*
- * Synchronize FP state for this process.
- */
-void
-fpusave_proc(struct lwp *l, int save)
-{
-	struct cpu_info *ci = curcpu();
-	struct cpu_info *oci;
-	struct pcb *pcb;
-#if defined(MULTIPROCESSOR)
-	u_long ipi = save ? ALPHA_IPI_SYNCH_FPU : ALPHA_IPI_DISCARD_FPU;
-	int s, spincount;
-#endif
-
-	pcb = lwp_getpcb(l);
-	KDASSERT(pcb != NULL);
-
-#if defined(MULTIPROCESSOR)
-	s = splhigh();		/* block IPIs for the duration */
-#endif
-	FPCPU_LOCK(pcb);
-
-	oci = pcb->pcb_fpcpu;
-	if (oci == NULL) {
-		FPCPU_UNLOCK(pcb);
-#if defined(MULTIPROCESSOR)
-		splx(s);
-#endif
-		return;
-	}
-
-#if defined(MULTIPROCESSOR)
-	if (oci == ci) {
-		KASSERT(ci->ci_fpcurlwp == l);
-		FPCPU_UNLOCK(pcb);
-		splx(s);
-		fpusave_cpu(ci, save);
-		return;
-	}
-
-	KASSERT(oci->ci_fpcurlwp == l);
-	alpha_send_ipi(oci->ci_cpuid, ipi);
-	FPCPU_UNLOCK(pcb);
-
-	spincount = 0;
-	while (pcb->pcb_fpcpu != NULL) {
-		spincount++;
-		delay(1000);	/* XXX */
-		if (spincount > 10000)
-			panic("fpsave ipi didn't");
-	}
-#else
-	KASSERT(ci->ci_fpcurlwp == l);
-	FPCPU_UNLOCK(pcb);
-	fpusave_cpu(ci, save);
-#endif /* MULTIPROCESSOR */
+	fpu_discard();
 }
 
 /*
@@ -1905,8 +1810,8 @@
 	*flags |= _UC_CPU | _UC_UNIQUE;
 
 	/* Save floating point register context, if any, and copy it. */
-	if (l->l_md.md_flags & MDP_FPUSED) {
-		fpusave_proc(l, 1);
+	if (fpu_used_p(l)) {
+		fpu_save();
 		(void)memcpy(&mcp->__fpregs, &pcb->pcb_fp,
 		    sizeof (mcp->__fpregs));
 		mcp->__fpregs.__fp_fpcr = alpha_read_fp_c(l);
@@ -1942,12 +1847,11 @@
 	/* Restore floating point register context, if any. */
 	if (flags & _UC_FPU) {
 		/* If we have an FP register context, get rid of it. */
-		if (pcb->pcb_fpcpu != NULL)
-			fpusave_proc(l, 0);
+		fpu_discard();
 		(void)memcpy(&pcb->pcb_fp, &mcp->__fpregs,
 		    sizeof (pcb->pcb_fp));
-		l->l_md.md_flags = mcp->__fpregs.__fp_fpcr & MDP_FP_C;
-		l->l_md.md_flags |= MDP_FPUSED;
+		l->l_md.md_flags = mcp->__fpregs.__fp_fpcr & MDLWP_FP_C;
+		fpu_mark_used(l);
 	}
 
 	return (0);

Index: src/sys/arch/alpha/alpha/process_machdep.c
diff -u src/sys/arch/alpha/alpha/process_machdep.c:1.25 src/sys/arch/alpha/alpha/process_machdep.c:1.26
--- src/sys/arch/alpha/alpha/process_machdep.c:1.25	Sat Nov 21 05:35:40 2009
+++ src/sys/arch/alpha/alpha/process_machdep.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: process_machdep.c,v 1.25 2009/11/21 05:35:40 rmind Exp $ */
+/* $NetBSD: process_machdep.c,v 1.26 2011/06/07 00:48:30 matt Exp $ */
 
 /*
  * Copyright (c) 1994 Christopher G. Demetriou
@@ -54,7 +54,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.25 2009/11/21 05:35:40 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.26 2011/06/07 00:48:30 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -116,8 +116,7 @@
 {
 	struct pcb *pcb = lwp_getpcb(l);
 
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 1);
+	fpu_save();
 
 	memcpy(regs, &pcb->pcb_fp, sizeof(struct fpreg));
 	return (0);
@@ -128,8 +127,8 @@
 {
 	struct pcb *pcb = lwp_getpcb(l);
 
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 0);
+	fpu_discard();
+	fpu_mark_used(l);
 
 	memcpy(&pcb->pcb_fp, regs, sizeof(struct fpreg));
 	return (0);

Index: src/sys/arch/alpha/alpha/trap.c
diff -u src/sys/arch/alpha/alpha/trap.c:1.125 src/sys/arch/alpha/alpha/trap.c:1.126
--- src/sys/arch/alpha/alpha/trap.c:1.125	Fri Apr 15 20:52:36 2011
+++ src/sys/arch/alpha/alpha/trap.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.125 2011/04/15 20:52:36 martin Exp $ */
+/* $NetBSD: trap.c,v 1.126 2011/06/07 00:48:30 matt Exp $ */
 
 /*-
  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -93,7 +93,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.125 2011/04/15 20:52:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.126 2011/06/07 00:48:30 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -123,9 +123,6 @@
 static int handle_opdec(struct lwp *l, u_long *ucodep);
 static int alpha_ucode_to_ksiginfo(u_long ucode);
 
-struct evcnt fpevent_use;
-struct evcnt fpevent_reuse;
-
 /*
  * Initialize the trap vectors for the current processor.
  */
@@ -360,8 +357,7 @@
 			break;
 
 		case ALPHA_IF_CODE_FEN:
-			alpha_enable_fp(l, 0);
-			alpha_pal_wrfen(0);
+			fpu_load();
 			goto out;
 
 		default:
@@ -563,71 +559,6 @@
 }
 
 /*
- * Set the float-point enable for the current process, and return
- * the FPU context to the named process. If check == 0, it is an
- * error for the named process to already be fpcurlwp.
- */
-void
-alpha_enable_fp(struct lwp *l, int check)
-{
-#if defined(MULTIPROCESSOR)
-	int s;
-#endif
-	struct cpu_info *ci = curcpu();
-	struct pcb *pcb;
-
-	if (check && ci->ci_fpcurlwp == l) {
-		alpha_pal_wrfen(1);
-		return;
-	}
-	if (ci->ci_fpcurlwp == l)
-		panic("trap: fp disabled for fpcurlwp == %p", l);
-
-	if (ci->ci_fpcurlwp != NULL)
-		fpusave_cpu(ci, 1);
-
-	KDASSERT(ci->ci_fpcurlwp == NULL);
-
-	pcb = lwp_getpcb(l);
-#if defined(MULTIPROCESSOR)
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 1);
-#else
-	KDASSERT(pcb->pcb_fpcpu == NULL);
-#endif
-
-#if defined(MULTIPROCESSOR)
-	s = splhigh();		/* block IPIs */
-#endif
-	FPCPU_LOCK(pcb);
-
-	pcb->pcb_fpcpu = ci;
-	ci->ci_fpcurlwp = l;
-
-	FPCPU_UNLOCK(pcb);
-#if defined(MULTIPROCESSOR)
-	splx(s);
-#endif
-
-	/*
-	 * Instrument FP usage -- if a process had not previously
-	 * used FP, mark it as having used FP for the first time,
-	 * and count this event.
-	 *
-	 * If a process has used FP, count a "used FP, and took
-	 * a trap to use it again" event.
-	 */
-	if ((l->l_md.md_flags & MDP_FPUSED) == 0) {
-		atomic_inc_ulong(&fpevent_use.ev_count);
-		l->l_md.md_flags |= MDP_FPUSED;
-	} else
-		atomic_inc_ulong(&fpevent_reuse.ev_count);
-
-	alpha_pal_wrfen(1);
-	restorefpstate(&pcb->pcb_fp);
-}
-
-/*
  * Process an asynchronous software trap.
  * This is relatively easy.
  */
@@ -687,10 +618,6 @@
 #define	frp(l, reg)							\
 	(&pcb->pcb_fp.fpr_regs[(reg)])
 
-#define	dump_fp_regs(pcb)						\
-	if (pcb->pcb_fpcpu != NULL)					\
-		fpusave_proc(l, 1)
-
 #define	unaligned_load(storage, ptrf, mod)				\
 	if (copyin((void *)va, &(storage), sizeof (storage)) != 0)	\
 		break;							\
@@ -714,14 +641,14 @@
 	unaligned_store(storage, irp, )
 
 #define	unaligned_load_floating(storage, mod) do {			\
-	struct pcb *pcb = lwp_getpcb(l);				\
-	dump_fp_regs(pcb);						\
+	struct pcb * const pcb = lwp_getpcb(l);				\
+	fpu_save();							\
 	unaligned_load(storage, frp, mod)				\
 } while (/*CONSTCOND*/0)
 
 #define	unaligned_store_floating(storage, mod) do {			\
-	struct pcb *pcb = lwp_getpcb(l);				\
-	dump_fp_regs(pcb);						\
+	struct pcb * const pcb = lwp_getpcb(l);				\
+	fpu_save();							\
 	unaligned_store(storage, frp, mod)				\
 } while (/*CONSTCOND*/0)
 

Index: src/sys/arch/alpha/alpha/vm_machdep.c
diff -u src/sys/arch/alpha/alpha/vm_machdep.c:1.106 src/sys/arch/alpha/alpha/vm_machdep.c:1.107
--- src/sys/arch/alpha/alpha/vm_machdep.c:1.106	Tue May 24 20:26:34 2011
+++ src/sys/arch/alpha/alpha/vm_machdep.c	Tue Jun  7 00:48:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: vm_machdep.c,v 1.106 2011/05/24 20:26:34 rmind Exp $ */
+/* $NetBSD: vm_machdep.c,v 1.107 2011/06/07 00:48:30 matt Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.106 2011/05/24 20:26:34 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.107 2011/06/07 00:48:30 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -50,12 +50,7 @@
 void
 cpu_lwp_free(struct lwp *l, int proc)
 {
-	struct pcb *pcb = lwp_getpcb(l);
-
-	if (pcb->pcb_fpcpu != NULL)
-		fpusave_proc(l, 0);
-
-	mutex_destroy(&pcb->pcb_fpcpu_lock);
+	(void) l;
 }
 
 void
@@ -93,7 +88,7 @@
 	pcb2 = lwp_getpcb(l2);
 
 	l2->l_md.md_tf = l1->l_md.md_tf;
-	l2->l_md.md_flags = l1->l_md.md_flags & (MDP_FPUSED | MDP_FP_C);
+	l2->l_md.md_flags = l1->l_md.md_flags & (MDLWP_FPUSED | MDLWP_FP_C);
 	l2->l_md.md_astpending = 0;
 
 	/*
@@ -103,15 +98,9 @@
 	l2->l_md.md_pcbpaddr = (void *)vtophys((vaddr_t)pcb2);
 
 	/*
-	 * Copy floating point state from the FP chip to the PCB
-	 * if this process has state stored there.
-	 */
-	if (pcb1->pcb_fpcpu != NULL)
-		fpusave_proc(l1, 1);
-
-	/*
 	 * Copy pcb and user stack pointer from proc p1 to p2.
 	 * If specificed, give the child a different stack.
+	 * Floating point state from the FP chip has already been saved.
 	 */
 	*pcb2 = *pcb1;
 	if (stack != NULL)
@@ -119,8 +108,6 @@
 	else
 		pcb2->pcb_hw.apcb_usp = alpha_pal_rdusp();
 
-	mutex_init(&pcb2->pcb_fpcpu_lock, MUTEX_DEFAULT, IPL_HIGH);
-
 	/*
 	 * Arrange for a non-local goto when the new process
 	 * is started, to resume here, returning nonzero from setjmp.

Index: src/sys/arch/alpha/include/alpha.h
diff -u src/sys/arch/alpha/include/alpha.h:1.25 src/sys/arch/alpha/include/alpha.h:1.26
--- src/sys/arch/alpha/include/alpha.h:1.25	Tue Feb  8 20:20:07 2011
+++ src/sys/arch/alpha/include/alpha.h	Tue Jun  7 00:48:31 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: alpha.h,v 1.25 2011/02/08 20:20:07 rmind Exp $ */
+/* $NetBSD: alpha.h,v 1.26 2011/06/07 00:48:31 matt Exp $ */
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -60,6 +60,8 @@
 #include <machine/bus.h>
 #include <machine/stdarg.h>
 
+#include <sys/pcu.h>
+
 struct pcb;
 struct lwp;
 struct reg;
@@ -107,8 +109,29 @@
 void	enable_nsio_ide(bus_space_tag_t);
 char *	dot_conv(unsigned long);
 
-void	fpusave_cpu(struct cpu_info *, int);
-void	fpusave_proc(struct lwp *, int);
+extern const pcu_ops_t fpu_ops;
+
+void    fpu_state_load(struct lwp *, bool);
+void    fpu_state_save(struct lwp *);
+void    fpu_state_release(struct lwp *);
+
+static inline void
+fpu_load(void)
+{
+	pcu_load(&fpu_ops);
+}
+
+static inline void
+fpu_save(void)
+{
+	pcu_save(&fpu_ops);
+}
+
+static inline void
+fpu_discard(void)
+{
+	pcu_discard(&fpu_ops);
+}
 
 void	alpha_patch(bool);
 
@@ -139,7 +162,6 @@
 u_int64_t alpha_read_fp_c(struct lwp *);
 void alpha_write_fp_c(struct lwp *, u_int64_t);
 
-void alpha_enable_fp(struct lwp *, int);
 int alpha_fp_complete(u_long, u_long, struct lwp *, u_int64_t *);
 
 /* Security sensitive rate limiting printf */

Index: src/sys/arch/alpha/include/intr.h
diff -u src/sys/arch/alpha/include/intr.h:1.68 src/sys/arch/alpha/include/intr.h:1.69
--- src/sys/arch/alpha/include/intr.h:1.68	Tue Jun 22 18:29:02 2010
+++ src/sys/arch/alpha/include/intr.h	Tue Jun  7 00:48:31 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.68 2010/06/22 18:29:02 rmind Exp $ */
+/* $NetBSD: intr.h,v 1.69 2011/06/07 00:48:31 matt Exp $ */
 
 /*-
  * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
@@ -162,12 +162,10 @@
 #define	ALPHA_IPI_SHOOTDOWN		(1UL << 2)
 #define	ALPHA_IPI_IMB			(1UL << 3)
 #define	ALPHA_IPI_AST			(1UL << 4)
-#define	ALPHA_IPI_SYNCH_FPU		(1UL << 5)
-#define	ALPHA_IPI_DISCARD_FPU		(1UL << 6)
-#define	ALPHA_IPI_PAUSE			(1UL << 7)
-#define	ALPHA_IPI_XCALL			(1UL << 8)
+#define	ALPHA_IPI_PAUSE			(1UL << 5)
+#define	ALPHA_IPI_XCALL			(1UL << 6)
 
-#define	ALPHA_NIPIS		9	/* must not exceed 64 */
+#define	ALPHA_NIPIS		7	/* must not exceed 64 */
 
 struct cpu_info;
 struct trapframe;

Index: src/sys/arch/alpha/include/pcb.h
diff -u src/sys/arch/alpha/include/pcb.h:1.19 src/sys/arch/alpha/include/pcb.h:1.20
--- src/sys/arch/alpha/include/pcb.h:1.19	Tue May 24 20:26:35 2011
+++ src/sys/arch/alpha/include/pcb.h	Tue Jun  7 00:48:31 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: pcb.h,v 1.19 2011/05/24 20:26:35 rmind Exp $ */
+/* $NetBSD: pcb.h,v 1.20 2011/06/07 00:48:31 matt Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -60,8 +60,6 @@
 	struct fpreg	pcb_fp;			/* FP registers		[SW] */
 	unsigned long	pcb_onfault;		/* for copy faults	[SW] */
 	unsigned long	pcb_accessaddr;		/* for [fs]uswintr	[SW] */
-	struct cpu_info * volatile pcb_fpcpu;	/* CPU with our FP state[SW] */
-	kmutex_t	pcb_fpcpu_lock;		/* lock on fpcpu	[SW] */
 };
 
 #define	FPCPU_LOCK(pcb)		mutex_enter(&(pcb)->pcb_fpcpu_lock)
Index: src/sys/arch/alpha/include/proc.h
diff -u src/sys/arch/alpha/include/proc.h:1.19 src/sys/arch/alpha/include/proc.h:1.20
--- src/sys/arch/alpha/include/proc.h:1.19	Fri Jan 14 02:06:22 2011
+++ src/sys/arch/alpha/include/proc.h	Tue Jun  7 00:48:31 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.19 2011/01/14 02:06:22 rmind Exp $ */
+/* $NetBSD: proc.h,v 1.20 2011/06/07 00:48:31 matt Exp $ */
 
 /*
  * Copyright (c) 1994, 1995 Carnegie-Mellon University.
@@ -37,31 +37,33 @@
  * Machine-dependent part of the lwp struct for the Alpha.
  */
 struct mdlwp {
-	u_long	md_flags;
-	struct	trapframe *md_tf;	/* trap/syscall registers */
+	u_long md_flags;		/* see below */
+	struct trapframe *md_tf;	/* trap/syscall registers */
 	struct pcb *md_pcbpaddr;	/* phys addr of the pcb */
-	volatile int md_astpending;	/* AST pending for this process */
+	volatile int md_astpending;	/* AST pending for this thread */
 };
+
 /*
  * md_flags usage
  * --------------
- * MDP_FPUSED
+ * MDLWP_FPUSED
  * 	A largely unused bit indicating the presence of FPU history.
  * 	Cleared on exec. Set but not used by the fpu context switcher
  * 	itself.
  * 
- * MDP_FP_C
+ * MDLWP_FP_C
  * 	The architected FP Control word. It should forever begin at bit 1,
  * 	as the bits are AARM specified and this way it doesn't need to be
  * 	shifted.
  * 
  * 	Until C99 there was never an IEEE 754 API, making most of the
  * 	standard useless.  Because of overlapping AARM, OSF/1, NetBSD, and
- * 	C99 API's, the use of the MDP_FP_C bits is defined variously in
+ * 	C99 API's, the use of the MDLWP_FP_C bits is defined variously in
  * 	ieeefp.h and fpu.h.
  */
-#define	MDP_FPUSED	0x00000001	/* Process used the FPU */
-#define	MDP_FP_C	0x007ffffe	/* Extended FP_C Quadword bits */
+#define	MDLWP_FPUSED	0x00000001	/* LWP used the FPU */
+#define	MDLWP_FP_C	0x007ffffe	/* Extended FP_C Quadword bits */
+#define	MDLWP_FPACTIVE	__BIT(63)	/* FPU is active on LWP's PCU CPU */
 
 /*
  * Machine-dependent part of the proc struct for the Alpha.
@@ -72,5 +74,10 @@
 	void	(*md_syscall)(struct lwp *, u_int64_t, struct trapframe *);
 };
 
+#ifdef _KERNEL
+#define	fpu_used_p(l)		(((l)->l_md.md_flags & MDLWP_FPUSED) != 0)
+#define	fpu_mark_used(l)	((void)((l)->l_md.md_flags |= MDLWP_FPUSED))
+#endif
+
 
 #endif /* !_ALPHA_PROC_H_ */

Index: src/sys/arch/alpha/include/types.h
diff -u src/sys/arch/alpha/include/types.h:1.45 src/sys/arch/alpha/include/types.h:1.46
--- src/sys/arch/alpha/include/types.h:1.45	Thu Mar 31 15:30:31 2011
+++ src/sys/arch/alpha/include/types.h	Tue Jun  7 00:48:31 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: types.h,v 1.45 2011/03/31 15:30:31 skrll Exp $ */
+/* $NetBSD: types.h,v 1.46 2011/06/07 00:48:31 matt Exp $ */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -84,4 +84,9 @@
 #define	__HAVE_RAS
 #endif
 
+#if defined(_KERNEL) || defined(_KMEMUSER)
+#define	PCU_FPU		0	/* FPU */
+#define	PCU_UNIT_COUNT	1
+#endif
+
 #endif	/* _MACHTYPES_H_ */

Index: src/sys/arch/mips/mips/mips_machdep.c
diff -u src/sys/arch/mips/mips/mips_machdep.c:1.240 src/sys/arch/mips/mips/mips_machdep.c:1.241
--- src/sys/arch/mips/mips/mips_machdep.c:1.240	Fri Apr 29 22:04:42 2011
+++ src/sys/arch/mips/mips/mips_machdep.c	Tue Jun  7 00:48:31 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_machdep.c,v 1.240 2011/04/29 22:04:42 matt Exp $	*/
+/*	$NetBSD: mips_machdep.c,v 1.241 2011/06/07 00:48:31 matt Exp $	*/
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -112,7 +112,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.240 2011/04/29 22:04:42 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.241 2011/06/07 00:48:31 matt Exp $");
 
 #define __INTR_PRIVATE
 #include "opt_cputype.h"
@@ -1498,8 +1498,6 @@
 	tf->tf_regs[_R_A2] = 0;
 	tf->tf_regs[_R_A3] = p->p_psstrp;
 
-	fpu_discard();
-	memset(&pcb->pcb_fpregs, 0, sizeof(struct fpreg));
 	l->l_md.md_ss_addr = 0;
 }
 

Index: src/sys/arch/powerpc/powerpc/fpu.c
diff -u src/sys/arch/powerpc/powerpc/fpu.c:1.29 src/sys/arch/powerpc/powerpc/fpu.c:1.30
--- src/sys/arch/powerpc/powerpc/fpu.c:1.29	Mon May  2 02:01:33 2011
+++ src/sys/arch/powerpc/powerpc/fpu.c	Tue Jun  7 00:48:32 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.c,v 1.29 2011/05/02 02:01:33 matt Exp $	*/
+/*	$NetBSD: fpu.c,v 1.30 2011/06/07 00:48:32 matt Exp $	*/
 
 /*
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.29 2011/05/02 02:01:33 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.30 2011/06/07 00:48:32 matt Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -80,6 +80,10 @@
 {
 	struct pcb * const pcb = lwp_getpcb(l);
 
+	if (__predict_false(!used)) {
+		memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu));
+	}
+
 	const register_t msr = mfmsr();
         mtmsr((msr & ~PSL_EE) | PSL_FP);
 	__asm volatile ("isync");

Index: src/sys/arch/powerpc/powerpc/powerpc_machdep.c
diff -u src/sys/arch/powerpc/powerpc/powerpc_machdep.c:1.49 src/sys/arch/powerpc/powerpc/powerpc_machdep.c:1.50
--- src/sys/arch/powerpc/powerpc/powerpc_machdep.c:1.49	Sun Jun  5 16:52:26 2011
+++ src/sys/arch/powerpc/powerpc/powerpc_machdep.c	Tue Jun  7 00:48:32 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: powerpc_machdep.c,v 1.49 2011/06/05 16:52:26 matt Exp $	*/
+/*	$NetBSD: powerpc_machdep.c,v 1.50 2011/06/07 00:48:32 matt Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: powerpc_machdep.c,v 1.49 2011/06/05 16:52:26 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: powerpc_machdep.c,v 1.50 2011/06/07 00:48:32 matt Exp $");
 
 #include "opt_altivec.h"
 #include "opt_modular.h"
@@ -127,10 +127,6 @@
 	tf->tf_vrsave = 0;
 #endif
 	pcb->pcb_flags = PSL_FE_DFLT;
-	memset(&pcb->pcb_fpu, 0, sizeof(&pcb->pcb_fpu));
-#if defined(ALTIVEC) || defined(PPC_SAVE_SPE)
-	memset(&pcb->pcb_vr, 0, sizeof(&pcb->pcb_vr));
-#endif
 }
 
 /*

Reply via email to