Module Name:    src
Committed By:   mrg
Date:           Thu Jan 13 05:20:27 UTC 2011

Modified Files:
        src/sys/arch/sparc/include: cpu.h
        src/sys/arch/sparc/sparc: cpu.c cpuvar.h genassym.cf locore.s machdep.c
            trap.c vm_machdep.c

Log Message:
introduce a hack to workaround the savefpstate IPI get's NULL
struct fpstate *.

add a new entry point ipi_savefpstate() that is used for this IPI
instead of the plain ipi_savefpstate().  check for %o0 being NULL,
and if so, just return.

add event counters for the savefpstate IPI, and another one for
when it detects the NULL problem.

make the cpu_info struct xmpsg be aligned to a single cache line.

with this change applied (and another minor change in testing) my
SS20 with dual SM75's has survived for 17 hours on build.sh -j5,
and has reported 7 NULL savefps.  (the minor change seems to have
a significant effect at reducing this number, but more testing is
needed for it.)

XXX:  this is horrible and we really need to find the real problem
XXX:  but this should let people use sparc smp again, and fixes
XXX:  for the real problem can be tested by seeing if any of the
XXX:  savefp IPI null counter becomes non-zero.


To generate a diff of this commit:
cvs rdiff -u -r1.89 -r1.90 src/sys/arch/sparc/include/cpu.h
cvs rdiff -u -r1.223 -r1.224 src/sys/arch/sparc/sparc/cpu.c
cvs rdiff -u -r1.83 -r1.84 src/sys/arch/sparc/sparc/cpuvar.h
cvs rdiff -u -r1.61 -r1.62 src/sys/arch/sparc/sparc/genassym.cf
cvs rdiff -u -r1.258 -r1.259 src/sys/arch/sparc/sparc/locore.s
cvs rdiff -u -r1.303 -r1.304 src/sys/arch/sparc/sparc/machdep.c
cvs rdiff -u -r1.184 -r1.185 src/sys/arch/sparc/sparc/trap.c
cvs rdiff -u -r1.101 -r1.102 src/sys/arch/sparc/sparc/vm_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/sparc/include/cpu.h
diff -u src/sys/arch/sparc/include/cpu.h:1.89 src/sys/arch/sparc/include/cpu.h:1.90
--- src/sys/arch/sparc/include/cpu.h:1.89	Sun Jan  3 23:03:21 2010
+++ src/sys/arch/sparc/include/cpu.h	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.89 2010/01/03 23:03:21 mrg Exp $ */
+/*	$NetBSD: cpu.h,v 1.90 2011/01/13 05:20:27 mrg Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -193,6 +193,7 @@
 
 /* locore.s */
 struct fpstate;
+void	ipi_savefpstate(struct fpstate *);
 void	savefpstate(struct fpstate *);
 void	loadfpstate(struct fpstate *);
 int	probeget(void *, int);

Index: src/sys/arch/sparc/sparc/cpu.c
diff -u src/sys/arch/sparc/sparc/cpu.c:1.223 src/sys/arch/sparc/sparc/cpu.c:1.224
--- src/sys/arch/sparc/sparc/cpu.c:1.223	Tue Jun 22 18:29:02 2010
+++ src/sys/arch/sparc/sparc/cpu.c	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.223 2010/06/22 18:29:02 rmind Exp $ */
+/*	$NetBSD: cpu.c,v 1.224 2011/01/13 05:20:27 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.223 2010/06/22 18:29:02 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.224 2011/01/13 05:20:27 mrg Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_lockdebug.h"
@@ -64,7 +64,9 @@
 #include <sys/device.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
+#include <sys/evcnt.h>
 #include <sys/xcall.h>
+#include <sys/cpu.h>
 
 #include <uvm/uvm.h>
 
@@ -119,6 +121,7 @@
     cpu_cpuunit_match, cpu_cpuunit_attach, NULL, NULL);
 #endif /* SUN4D */
 
+static void cpu_init_evcnt(struct cpu_info *cpi);
 static void cpu_attach(struct cpu_softc *, int, int);
 
 static const char *fsrtoname(int, int, int);
@@ -293,6 +296,21 @@
 }
 #endif /* SUN4D */
 
+static void
+cpu_init_evcnt(struct cpu_info *cpi)
+{
+
+	/*
+	 * Setup the per-cpu savefpstate counters.  The "savefp null"
+	 * counter should go away when the NULL struct fpstate * bug
+	 * is fixed.
+	 */
+	evcnt_attach_dynamic(&cpi->ci_savefpstate, EVCNT_TYPE_MISC,
+			     NULL, cpu_name(cpi), "savefp ipi");
+	evcnt_attach_dynamic(&cpi->ci_savefpstate_null, EVCNT_TYPE_MISC,
+			     NULL, cpu_name(cpi), "savefp null ipi");
+}
+
 /*
  * Attach the CPU.
  * Discover interesting goop about the virtual address cache
@@ -341,10 +359,13 @@
 #if defined(MULTIPROCESSOR)
 	if (cpu_attach_count > 1) {
 		cpu_attach_non_boot(sc, cpi, node);
+		cpu_init_evcnt(cpi);
 		return;
 	}
 #endif /* MULTIPROCESSOR */
 
+	cpu_init_evcnt(cpi);
+
 	/* Stuff to only run on the boot CPU */
 	cpu_setup();
 	snprintf(buf, sizeof buf, "%s @ %s MHz, %s FPU",

Index: src/sys/arch/sparc/sparc/cpuvar.h
diff -u src/sys/arch/sparc/sparc/cpuvar.h:1.83 src/sys/arch/sparc/sparc/cpuvar.h:1.84
--- src/sys/arch/sparc/sparc/cpuvar.h:1.83	Sat Jan 23 16:06:57 2010
+++ src/sys/arch/sparc/sparc/cpuvar.h	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuvar.h,v 1.83 2010/01/23 16:06:57 mrg Exp $ */
+/*	$NetBSD: cpuvar.h,v 1.84 2011/01/13 05:20:27 mrg Exp $ */
 
 /*
  *  Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -127,6 +127,13 @@
 struct cpu_info {
 	struct cpu_data ci_data;	/* MI per-cpu data */
 
+	/*
+	 * Primary Inter-processor message area.  Keep this aligned
+	 * to a cache line boundary if possible, as the structure
+	 * itself is one (normal 32 byte) cache-line.
+	 */
+	struct xpmsg	msg __aligned(32);
+
 	/* Scheduler flags */
 	int	ci_want_ast;
 	int	ci_want_resched;
@@ -142,9 +149,6 @@
 	 */
 	struct cpu_info * volatile ci_self;
 
-	/* Primary Inter-processor message area */
-	struct xpmsg	msg;
-
 	int		ci_cpuid;	/* CPU index (see cpus[] array) */
 
 	/* Context administration */
@@ -334,6 +338,8 @@
 
 	struct evcnt ci_lev10;
 	struct evcnt ci_lev14;
+	struct evcnt ci_savefpstate;
+	struct evcnt ci_savefpstate_null;
 };
 
 /*

Index: src/sys/arch/sparc/sparc/genassym.cf
diff -u src/sys/arch/sparc/sparc/genassym.cf:1.61 src/sys/arch/sparc/sparc/genassym.cf:1.62
--- src/sys/arch/sparc/sparc/genassym.cf:1.61	Mon Dec 20 00:25:44 2010
+++ src/sys/arch/sparc/sparc/genassym.cf	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.61 2010/12/20 00:25:44 matt Exp $
+#	$NetBSD: genassym.cf,v 1.62 2011/01/13 05:20:27 mrg Exp $
 
 #
 # Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -166,6 +166,8 @@
 define	CPUINFO_MTX_COUNT	offsetof(struct cpu_info, ci_mtx_count)
 define	CPUINFO_MTX_OLDSPL	offsetof(struct cpu_info, ci_mtx_oldspl)
 define	CPUINFO_IDEPTH		offsetof(struct cpu_info, ci_idepth)
+define	CPUINFO_SAVEFPSTATE	offsetof(struct cpu_info, ci_savefpstate)
+define	CPUINFO_SAVEFPSTATE_NULL offsetof(struct cpu_info, ci_savefpstate_null)
 
 # PTE bits and related information
 define	PG_W		PG_W

Index: src/sys/arch/sparc/sparc/locore.s
diff -u src/sys/arch/sparc/sparc/locore.s:1.258 src/sys/arch/sparc/sparc/locore.s:1.259
--- src/sys/arch/sparc/sparc/locore.s:1.258	Mon Dec 20 00:25:44 2010
+++ src/sys/arch/sparc/sparc/locore.s	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.s,v 1.258 2010/12/20 00:25:44 matt Exp $	*/
+/*	$NetBSD: locore.s,v 1.259 2011/01/13 05:20:27 mrg Exp $	*/
 
 /*
  * Copyright (c) 1996 Paul Kranenburg
@@ -5841,12 +5841,29 @@
 	/* NOTREACHED */
 
 /*
- * savefpstate(f) struct fpstate *f;
+ * savefpstate(struct fpstate *f);
+ * ipi_savefpstate(struct fpstate *f);
  *
  * Store the current FPU state.  The first `st %fsr' may cause a trap;
  * our trap handler knows how to recover (by `returning' to savefpcont).
+ *
+ * The IPI version just deals with updating event counters first.
  */
+Lpanic_savefpstate:
+	.asciz	"cpu%d: NULL fpstate"
+	_ALIGN
+
+ENTRY(ipi_savefpstate)
+	sethi	%hi(CPUINFO_VA), %o5
+	ldd	[%o5 + CPUINFO_SAVEFPSTATE], %o2
+	inccc   %o3
+	addx    %o2, 0, %o2
+	std	%o2, [%o5 + CPUINFO_SAVEFPSTATE]
+
 ENTRY(savefpstate)
+	cmp	%o0, 0
+	bz	Lfp_null_fpstate
+	 nop
 	rd	%psr, %o1		! enable FP before we begin
 	set	PSR_EF, %o2
 	or	%o1, %o2, %o1
@@ -5889,6 +5906,27 @@
 	 std	%f30, [%o0 + FS_REGS + (4*30)]
 
 /*
+ * We really should panic here but while we figure out what the bug is
+ * that a remote CPU gets a NULL struct fpstate *, this lets the system
+ * work at least seemingly stably.
+ */
+Lfp_null_fpstate:
+#if 1
+	sethi	%hi(CPUINFO_VA), %o5
+	ldd	[%o5 + CPUINFO_SAVEFPSTATE_NULL], %o2
+	inccc   %o3
+	addx    %o2, 0, %o2
+	retl
+	 std	%o2, [%o5 + CPUINFO_SAVEFPSTATE_NULL]
+#else
+	ld	[%o5 + CPUINFO_CPUNO], %o1
+	sethi	%hi(Lpanic_savefpstate), %o0
+	call	_C_LABEL(panic)
+	 or	%o0, %lo(Lpanic_savefpstate), %o0
+#endif
+1:
+
+/*
  * Store the (now known nonempty) FP queue.
  * We have to reread the fsr each time in order to get the new QNE bit.
  */

Index: src/sys/arch/sparc/sparc/machdep.c
diff -u src/sys/arch/sparc/sparc/machdep.c:1.303 src/sys/arch/sparc/sparc/machdep.c:1.304
--- src/sys/arch/sparc/sparc/machdep.c:1.303	Mon Dec 20 00:25:44 2010
+++ src/sys/arch/sparc/sparc/machdep.c	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.303 2010/12/20 00:25:44 matt Exp $ */
+/*	$NetBSD: machdep.c,v 1.304 2011/01/13 05:20:27 mrg Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.303 2010/12/20 00:25:44 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.304 2011/01/13 05:20:27 mrg Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_compat_sunos.h"
@@ -376,7 +376,7 @@
 				savefpstate(fs);
 #if defined(MULTIPROCESSOR)
 			else
-				XCALL1(savefpstate, fs, 1 << cpi->ci_cpuid);
+				XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid);
 #endif
 			cpi->fplwp = NULL;
 		}

Index: src/sys/arch/sparc/sparc/trap.c
diff -u src/sys/arch/sparc/sparc/trap.c:1.184 src/sys/arch/sparc/sparc/trap.c:1.185
--- src/sys/arch/sparc/sparc/trap.c:1.184	Mon Dec 20 00:25:44 2010
+++ src/sys/arch/sparc/sparc/trap.c	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.184 2010/12/20 00:25:44 matt Exp $ */
+/*	$NetBSD: trap.c,v 1.185 2011/01/13 05:20:27 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.184 2010/12/20 00:25:44 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.185 2011/01/13 05:20:27 mrg Exp $");
 
 #include "opt_ddb.h"
 #include "opt_compat_svr4.h"
@@ -477,7 +477,7 @@
 					panic("FPU(%d): state for %p",
 							cpi->ci_cpuid, l);
 #if defined(MULTIPROCESSOR)
-				XCALL1(savefpstate, fs, 1 << cpi->ci_cpuid);
+				XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid);
 #endif
 				cpi->fplwp = NULL;
 			}

Index: src/sys/arch/sparc/sparc/vm_machdep.c
diff -u src/sys/arch/sparc/sparc/vm_machdep.c:1.101 src/sys/arch/sparc/sparc/vm_machdep.c:1.102
--- src/sys/arch/sparc/sparc/vm_machdep.c:1.101	Sat Nov 21 04:16:52 2009
+++ src/sys/arch/sparc/sparc/vm_machdep.c	Thu Jan 13 05:20:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: vm_machdep.c,v 1.101 2009/11/21 04:16:52 rmind Exp $ */
+/*	$NetBSD: vm_machdep.c,v 1.102 2011/01/13 05:20:27 mrg Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.101 2009/11/21 04:16:52 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.102 2011/01/13 05:20:27 mrg Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -228,7 +228,7 @@
 				savefpstate(l1->l_md.md_fpstate);
 #if defined(MULTIPROCESSOR)
 			else
-				XCALL1(savefpstate, l1->l_md.md_fpstate,
+				XCALL1(ipi_savefpstate, l1->l_md.md_fpstate,
 					1 << cpi->ci_cpuid);
 #endif
 		}
@@ -306,7 +306,7 @@
 				savefpstate(fs);
 #if defined(MULTIPROCESSOR)
 			else
-				XCALL1(savefpstate, fs, 1 << cpi->ci_cpuid);
+				XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid);
 #endif
 			cpi->fplwp = NULL;
 		}

Reply via email to