Module Name:    src
Committed By:   riz
Date:           Tue Mar  8 17:29:46 UTC 2011

Modified Files:
        src/sys/arch/sparc/dev [netbsd-5]: zs.c
        src/sys/arch/sparc/include [netbsd-5]: cpu.h z8530var.h
        src/sys/arch/sparc/sparc [netbsd-5]: cpu.c cpuvar.h db_interface.c
            genassym.cf intr.c locore.s machdep.c timer.c timer_sun4m.c
            timervar.h trap.c vm_machdep.c

Log Message:
Apply patches (requested by mrg in ticket #1564):
        sys/arch/sparc/dev/zs.c:                patch
        sys/arch/sparc/include/cpu.h:           patch
        sys/arch/sparc/include/z8530var.h:      patch
        sys/arch/sparc/sparc/cpu.c:             patch
        sys/arch/sparc/sparc/cpuvar.h:          patch
        sys/arch/sparc/sparc/db_interface.c:    patch
        sys/arch/sparc/sparc/genassym.cf:       patch
        sys/arch/sparc/sparc/intr.c:            patch
        sys/arch/sparc/sparc/locore.s:          patch
        sys/arch/sparc/sparc/machdep.c:         patch
        sys/arch/sparc/sparc/timer.c:           patch
        sys/arch/sparc/sparc/timer_sun4m.c:     patch
        sys/arch/sparc/sparc/timervar.h:        patch
        sys/arch/sparc/sparc/trap.c:            patch
        sys/arch/sparc/sparc/vm_machdep.c:      patch

- fix a panic in savefpstate.  idea, and code suggestions from uwe
- convert xpmsg_lock to IPL_SCHED.  the old spl/simple_lock code ran at
  splsched(), and this significantly helps with stability under load when
  running with multiple active CPUs
- in strayintr() don't print about stray zs inters in MP case
- fix a deadlock in xcall()
- consolidate the interrupt evcnt(9) into a full set of per-IPL per-CPU
  soft/hard counters
- fix xcall() failure messages in some cases
- addd new ddb command "mach xcall"
- use schedintr() (not schedintr_4m()) on MP or single CPU configurations
- call hardclock() the same way on cpu0 in MP and !MP cases
- request the appropriate stack space for nmi_sun4m, in particular,
  make sure we have space for %g2...%g5.  now entering ddb via eg,
  serial break no longer causes cpu1 to fault.
- give memfault_sun*() some entry points that both gdb and ddb will find.
from tsutsui:
- fix panic in interrupt handlers in zs


To generate a diff of this commit:
cvs rdiff -u -r1.111.6.3 -r1.111.6.4 src/sys/arch/sparc/dev/zs.c
cvs rdiff -u -r1.84.14.1 -r1.84.14.2 src/sys/arch/sparc/include/cpu.h
cvs rdiff -u -r1.9 -r1.9.14.1 src/sys/arch/sparc/include/z8530var.h
cvs rdiff -u -r1.211.8.4 -r1.211.8.5 src/sys/arch/sparc/sparc/cpu.c
cvs rdiff -u -r1.75.10.4 -r1.75.10.5 src/sys/arch/sparc/sparc/cpuvar.h
cvs rdiff -u -r1.79.4.2 -r1.79.4.3 src/sys/arch/sparc/sparc/db_interface.c
cvs rdiff -u -r1.56.4.1 -r1.56.4.2 src/sys/arch/sparc/sparc/genassym.cf
cvs rdiff -u -r1.100.20.2 -r1.100.20.3 src/sys/arch/sparc/sparc/intr.c
cvs rdiff -u -r1.244.8.3 -r1.244.8.4 src/sys/arch/sparc/sparc/locore.s
cvs rdiff -u -r1.282.4.3 -r1.282.4.4 src/sys/arch/sparc/sparc/machdep.c
cvs rdiff -u -r1.23 -r1.23.28.1 src/sys/arch/sparc/sparc/timer.c
cvs rdiff -u -r1.16.56.2 -r1.16.56.3 src/sys/arch/sparc/sparc/timer_sun4m.c
cvs rdiff -u -r1.8 -r1.8.74.1 src/sys/arch/sparc/sparc/timervar.h
cvs rdiff -u -r1.176 -r1.176.4.1 src/sys/arch/sparc/sparc/trap.c
cvs rdiff -u -r1.95.4.2 -r1.95.4.3 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/dev/zs.c
diff -u src/sys/arch/sparc/dev/zs.c:1.111.6.3 src/sys/arch/sparc/dev/zs.c:1.111.6.4
--- src/sys/arch/sparc/dev/zs.c:1.111.6.3	Sun Jan 16 12:54:42 2011
+++ src/sys/arch/sparc/dev/zs.c	Tue Mar  8 17:29:45 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: zs.c,v 1.111.6.3 2011/01/16 12:54:42 bouyer Exp $	*/
+/*	$NetBSD: zs.c,v 1.111.6.4 2011/03/08 17:29:45 riz Exp $	*/
 
 /*-
  * Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.111.6.3 2011/01/16 12:54:42 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.111.6.4 2011/03/08 17:29:45 riz Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -171,12 +171,8 @@
 
 extern struct cfdriver zs_cd;
 
-/* softintr(9) cookie, shared by all instances of this driver */
-static void *zs_sicookie;
-
 /* Interrupt handlers. */
 static int zshard(void *);
-static void zssoft(void *);
 
 static int zs_get_speed(struct zs_chanstate *);
 
@@ -396,7 +392,6 @@
 	struct zsc_attach_args zsc_args;
 	struct zs_chanstate *cs;
 	int channel;
-	static int didintr, prevpri;
 #if (NKBD > 0) || (NMS > 0)
 	int ch0_is_cons = 0;
 #endif
@@ -407,12 +402,11 @@
 		return;
 	}
 
-	if (!didintr) {
-		zs_sicookie = softint_establish(SOFTINT_SERIAL, zssoft, NULL);
-		if (zs_sicookie == NULL) {
-			aprint_error(": cannot establish soft int handler\n");
-			return;
-		}
+	zsc->zsc_sicookie = softint_establish(SOFTINT_SERIAL,
+	    (void (*)(void *))zsc_intr_soft, zsc);
+	if (zsc->zsc_sicookie == NULL) {
+		aprint_error(": cannot establish soft int handler\n");
+		return;
 	}
 	aprint_normal(" softpri %d\n", IPL_SOFTSERIAL);
 
@@ -551,17 +545,9 @@
 	}
 
 	/*
-	 * Now safe to install interrupt handlers.  Note the arguments
-	 * to the interrupt handlers aren't used.  Note, we only do this
-	 * once since both SCCs interrupt at the same level and vector.
+	 * Now safe to install interrupt handlers.
 	 */
-	if (!didintr) {
-		didintr = 1;
-		prevpri = pri;
-		bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL,
-				   zshard, NULL);
-	} else if (pri != prevpri)
-		panic("broken zs interrupt scheme");
+	bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, zshard, zsc);
 
 	evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL,
 	    device_xname(zsc->zsc_dev), "intr");
@@ -610,81 +596,29 @@
 static volatile int zssoftpending;
 
 /*
- * Our ZS chips all share a common, autovectored interrupt,
- * so we have to look at all of them on each interrupt.
+ * Our ZS chips all share a common interrupt level,
+ * but we establish zshard handler per each ZS chips
+ * to avoid holding unnecessary locks in interrupt context.
  */
 static int
 zshard(void *arg)
 {
-	struct zsc_softc *zsc;
-	int unit, rr3, rval, softreq;
+	struct zsc_softc *zsc = arg;
+	int rr3, rval;
 
-	rval = softreq = 0;
-	for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
-		struct zs_chanstate *cs;
-
-		zsc = device_lookup_private(&zs_cd, unit);
-		if (zsc == NULL)
-			continue;
-		rr3 = zsc_intr_hard(zsc);
-		/* Count up the interrupts. */
-		if (rr3) {
-			rval |= rr3;
-			zsc->zsc_intrcnt.ev_count++;
-		}
-		if ((cs = zsc->zsc_cs[0]) != NULL)
-			softreq |= cs->cs_softreq;
-		if ((cs = zsc->zsc_cs[1]) != NULL)
-			softreq |= cs->cs_softreq;
-	}
-
-	/* We are at splzs here, so no need to lock. */
-	if (softreq && (zssoftpending == 0)) {
-		zssoftpending = 1;
-		softint_schedule(zs_sicookie);
+	rval = 0;
+	rr3 = zsc_intr_hard(zsc);
+	/* Count up the interrupts. */
+	if (rr3) {
+		rval = rr3;
+		zsc->zsc_intrcnt.ev_count++;
 	}
+	if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq)
+		softint_schedule(zsc->zsc_sicookie);
 	return (rval);
 }
 
 /*
- * Similar scheme as for zshard (look at all of them)
- */
-static void
-zssoft(void *arg)
-{
-	struct zsc_softc *zsc;
-	int unit;
-
-	/* This is not the only ISR on this IPL. */
-	if (zssoftpending == 0)
-		return;
-
-	/*
-	 * The soft intr. bit will be set by zshard only if
-	 * the variable zssoftpending is zero.  The order of
-	 * these next two statements prevents our clearing
-	 * the soft intr bit just after zshard has set it.
-	 */
-	/* ienab_bic(IE_ZSSOFT); */
-	zssoftpending = 0;
-
-#if 0 /* not yet */
-	/* Make sure we call the tty layer with tty_lock held. */
-	mutex_spin_enter(&tty_lock);
-#endif
-	for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
-		zsc = device_lookup_private(&zs_cd, unit);
-		if (zsc == NULL)
-			continue;
-		(void)zsc_intr_soft(zsc);
-	}
-#if 0 /* not yet */
-	mutex_spin_exit(&tty_lock);
-#endif
-}
-
-
-/*
  * Compute the current baud rate given a ZS channel.
  */
 static int

Index: src/sys/arch/sparc/include/cpu.h
diff -u src/sys/arch/sparc/include/cpu.h:1.84.14.1 src/sys/arch/sparc/include/cpu.h:1.84.14.2
--- src/sys/arch/sparc/include/cpu.h:1.84.14.1	Sat Jan  9 01:43:51 2010
+++ src/sys/arch/sparc/include/cpu.h	Tue Mar  8 17:29:45 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.84.14.1 2010/01/09 01:43:51 snj Exp $ */
+/*	$NetBSD: cpu.h,v 1.84.14.2 2011/03/08 17:29:45 riz Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -191,6 +191,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/include/z8530var.h
diff -u src/sys/arch/sparc/include/z8530var.h:1.9 src/sys/arch/sparc/include/z8530var.h:1.9.14.1
--- src/sys/arch/sparc/include/z8530var.h:1.9	Sat Mar 29 19:15:35 2008
+++ src/sys/arch/sparc/include/z8530var.h	Tue Mar  8 17:29:45 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: z8530var.h,v 1.9 2008/03/29 19:15:35 tsutsui Exp $	*/
+/*	$NetBSD: z8530var.h,v 1.9.14.1 2011/03/08 17:29:45 riz Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -54,6 +54,7 @@
 	int			zsc_node;	/* PROM node, if any */
 	struct evcnt		zsc_intrcnt;	/* count interrupts */
 	struct zs_chanstate	zsc_cs_store[2];
+	void			*zsc_sicookie;	/* softint(9) cookie */
 };
 
 /*

Index: src/sys/arch/sparc/sparc/cpu.c
diff -u src/sys/arch/sparc/sparc/cpu.c:1.211.8.4 src/sys/arch/sparc/sparc/cpu.c:1.211.8.5
--- src/sys/arch/sparc/sparc/cpu.c:1.211.8.4	Wed Feb 16 21:33:25 2011
+++ src/sys/arch/sparc/sparc/cpu.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.211.8.4 2011/02/16 21:33:25 bouyer Exp $ */
+/*	$NetBSD: cpu.c,v 1.211.8.5 2011/03/08 17:29:46 riz Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211.8.4 2011/02/16 21:33:25 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.211.8.5 2011/03/08 17:29:46 riz Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_lockdebug.h"
@@ -65,6 +65,8 @@
 #include <sys/malloc.h>
 #include <sys/simplelock.h>
 #include <sys/kernel.h>
+#include <sys/evcnt.h>
+#include <sys/cpu.h>
 
 #include <uvm/uvm.h>
 
@@ -78,6 +80,7 @@
 #include <machine/pmap.h>
 
 #if defined(MULTIPROCESSOR) && defined(DDB)
+#include <ddb/db_output.h>
 #include <machine/db_machdep.h>
 #endif
 
@@ -119,6 +122,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 +297,71 @@
 }
 #endif /* SUN4D */
 
+static const char * const hard_intr_names[] = {
+	"spur hard",
+	"lev1 hard",
+	"lev2 hard",
+	"lev3 hard",
+	"lev4 hard",
+	"lev5 hard",
+	"lev6 hard",
+	"lev7 hard",
+	"lev8 hard",
+	"lev9 hard",
+	"clock hard",
+	"lev11 hard",
+	"lev12 hard",
+	"lev13 hard",
+	"prof hard",
+	"nmi hard",
+};
+
+static const char * const soft_intr_names[] = {
+	"spur soft",
+	"lev1 soft",
+	"lev2 soft",
+	"lev3 soft",
+	"lev4 soft",
+	"lev5 soft",
+	"lev6 soft",
+	"lev7 soft",
+	"lev8 soft",
+	"lev9 soft",
+	"lev10 soft",
+	"lev11 soft",
+	"lev12 soft",
+	"xcall std",
+	"xcall fast",
+	"nmi soft",
+};
+
+static void
+cpu_init_evcnt(struct cpu_info *cpi)
+{
+	int i;
+
+	/*
+	 * Setup the per-cpu counters.
+	 */
+	snprintf(cpi->ci_cpuname, sizeof(cpi->ci_cpuname), "cpu/%d", cpi->ci_cpuid);
+	evcnt_attach_dynamic(&cpi->ci_savefpstate, EVCNT_TYPE_MISC,
+			     NULL, cpi->ci_cpuname, "savefp ipi");
+	evcnt_attach_dynamic(&cpi->ci_xpmsg_mutex_fail, EVCNT_TYPE_MISC,
+			     NULL, cpi->ci_cpuname, "IPI mutex_trylock fail");
+	evcnt_attach_dynamic(&cpi->ci_xpmsg_mutex_fail_call, EVCNT_TYPE_MISC,
+			     NULL, cpi->ci_cpuname, "IPI mutex_trylock fail/call");
+
+	/*
+	 * These are the per-cpu per-IPL hard & soft interrupt counters.
+	 */
+	for (i = 0; i < 16; i++) {
+		evcnt_attach_dynamic(&cpi->ci_intrcnt[i], EVCNT_TYPE_INTR,
+				     NULL, cpi->ci_cpuname, hard_intr_names[i]);
+		evcnt_attach_dynamic(&cpi->ci_sintrcnt[i], EVCNT_TYPE_INTR,
+				     NULL, cpi->ci_cpuname, soft_intr_names[i]);
+	}
+}
+
 /*
  * Attach the CPU.
  * Discover interesting goop about the virtual address cache
@@ -341,10 +410,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",
@@ -500,7 +572,7 @@
 cpu_init_system(void)
 {
 
-	mutex_init(&xpmsg_mutex, MUTEX_SPIN, IPL_VM);
+	mutex_init(&xpmsg_mutex, MUTEX_SPIN, IPL_SCHED);
 }
 
 /*
@@ -560,8 +632,12 @@
 	struct cpu_info *cpi;
 	int n, i, done, callself, mybit;
 	volatile struct xpmsg_func *p;
+	u_int pil;
 	int fasttrap;
 	int is_noop = func == (xcall_func_t)sparc_noop;
+	static char errbuf[160];
+	char *bufp = errbuf;
+	size_t bufsz = sizeof errbuf, wrsz;
 
 	mybit = (1 << cpuinfo.ci_cpuid);
 	callself = func && (cpuset & mybit) != 0;
@@ -571,7 +647,34 @@
 	cpuset &= cpu_ready_mask;
 
 	/* prevent interrupts that grab the kernel lock */
+#if 0
 	mutex_spin_enter(&xpmsg_mutex);
+#else
+	/*
+	 * There's a deadlock potential between multiple CPUs trying
+	 * to xcall() at the same time, and the thread that loses the
+	 * race to get xpmsg_lock is at an IPL above the incoming IPI
+	 * IPL level, so it sits around waiting to take the lock while
+	 * the other CPU is waiting for this CPU to handle the IPI and
+	 * mark it as completed.
+	 *
+	 * If we fail to get the mutex, and we're at high enough IPL,
+	 * call xcallintr() if there is a valid msg.tag.
+	 */
+	pil = (getpsr() & PSR_PIL) >> 8;
+	
+	if (cold || pil < 13)
+		mutex_spin_enter(&xpmsg_mutex);
+	else {
+		while (mutex_tryenter(&xpmsg_mutex) == 0) {
+			cpuinfo.ci_xpmsg_mutex_fail.ev_count++;
+			if (cpuinfo.msg.tag) {
+				cpuinfo.ci_xpmsg_mutex_fail_call.ev_count++;
+				xcallintr(xcallintr);
+			}
+		}
+	}
+#endif
 
 	/*
 	 * Firstly, call each CPU.  We do this so that they might have
@@ -599,7 +702,6 @@
 	/*
 	 * Second, call ourselves.
 	 */
-	p = &cpuinfo.msg.u.xpmsg_func;
 	if (callself)
 		(*func)(arg0, arg1, arg2);
 
@@ -612,8 +714,11 @@
 	i = 100000;	/* time-out, not too long, but still an _AGE_ */
 	while (!done) {
 		if (--i < 0) {
-			printf_nolog("xcall(cpu%d,%p): couldn't ping cpus:",
+			wrsz = snprintf(bufp, bufsz,
+			    "xcall(cpu%d,%p): couldn't ping cpus:",
 			    cpu_number(), func);
+			bufsz -= wrsz;
+			bufp += wrsz;
 		}
 
 		done = 1;
@@ -623,7 +728,13 @@
 
 			if (cpi->msg.complete == 0) {
 				if (i < 0) {
-					printf_nolog(" cpu%d", cpi->ci_cpuid);
+					wrsz = snprintf(bufp, bufsz,
+							" cpu%d", cpi->ci_cpuid);
+					bufsz -= wrsz;
+					bufp += wrsz;
+					/* insanity */
+					if (bufsz < 0)
+						break;
 				} else {
 					done = 0;
 					break;
@@ -632,8 +743,7 @@
 		}
 	}
 	if (i < 0)
-		printf_nolog("\n");
-
+		printf_nolog("%s\n", errbuf);
 	mutex_spin_exit(&xpmsg_mutex);
 }
 
@@ -2033,8 +2143,6 @@
 
 #include "ioconf.h"
 
-void cpu_debug_dump(void);
-
 /*
  * Dump CPU information from ddb.
  */
@@ -2057,4 +2165,35 @@
 		    ci->curpcb);
 	}
 }
+
+#if defined(MULTIPROCESSOR)
+/*
+ * Dump CPU xcall from ddb.
+ */
+void
+cpu_xcall_dump(void)
+{
+	struct cpu_info *ci;
+	CPU_INFO_ITERATOR cii;
+
+	db_printf("%-4s %-10s %-10s %-10s %-10s %-10s "
+		    "%-4s %-4s %-4s\n",
+	          "CPU#", "FUNC", "TRAP", "ARG0", "ARG1", "ARG2",
+	            "TAG", "RECV", "COMPL");
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		db_printf("%-4d %-10p %-10p 0x%-8x 0x%-8x 0x%-8x "
+			    "%-4d %-4d %-4d\n",
+		    ci->ci_cpuid,
+		    ci->msg.u.xpmsg_func.func,
+		    ci->msg.u.xpmsg_func.trap,
+		    ci->msg.u.xpmsg_func.arg0,
+		    ci->msg.u.xpmsg_func.arg1,
+		    ci->msg.u.xpmsg_func.arg2,
+		    ci->msg.tag,
+		    ci->msg.received,
+		    ci->msg.complete);
+	}
+}
+#endif
+
 #endif

Index: src/sys/arch/sparc/sparc/cpuvar.h
diff -u src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.4 src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.5
--- src/sys/arch/sparc/sparc/cpuvar.h:1.75.10.4	Wed Feb 16 21:33:25 2011
+++ src/sys/arch/sparc/sparc/cpuvar.h	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuvar.h,v 1.75.10.4 2011/02/16 21:33:25 bouyer Exp $ */
+/*	$NetBSD: cpuvar.h,v 1.75.10.5 2011/03/08 17:29:46 riz 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 */
@@ -333,8 +337,11 @@
 	vaddr_t	ci_free_sva1, ci_free_eva1, ci_free_sva2, ci_free_eva2;
 
 	char ci_cpuname[8];	/* "cpu/0", etc. */
-	struct evcnt ci_lev10;
-	struct evcnt ci_lev14;
+	struct evcnt ci_savefpstate;
+	struct evcnt ci_xpmsg_mutex_fail;
+	struct evcnt ci_xpmsg_mutex_fail_call;
+	struct evcnt ci_intrcnt[16];
+	struct evcnt ci_sintrcnt[16];
 };
 
 /*
@@ -448,6 +455,8 @@
 typedef void (*xcall_func_t)(int, int, int);
 typedef void (*xcall_trap_t)(int, int, int);
 void xcall(xcall_func_t, xcall_trap_t, int, int, int, u_int);
+/* from intr.c */
+void xcallintr(void *);
 /* Shorthand */
 #define XCALL0(f,cpuset)		\
 	xcall((xcall_func_t)f, NULL, 0, 0, 0, cpuset)
@@ -487,5 +496,12 @@
 
 #define cpuinfo	(*(struct cpu_info *)CPUINFO_VA)
 
+#if defined(DDB) || defined(MULTIPROCESSOR)
+/*
+ * These are called by ddb mach functions.
+ */
+void cpu_debug_dump(void);
+void cpu_xcall_dump(void);
+#endif
 
 #endif	/* _sparc_cpuvar_h */

Index: src/sys/arch/sparc/sparc/db_interface.c
diff -u src/sys/arch/sparc/sparc/db_interface.c:1.79.4.2 src/sys/arch/sparc/sparc/db_interface.c:1.79.4.3
--- src/sys/arch/sparc/sparc/db_interface.c:1.79.4.2	Sun Jan 16 12:58:24 2011
+++ src/sys/arch/sparc/sparc/db_interface.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_interface.c,v 1.79.4.2 2011/01/16 12:58:24 bouyer Exp $ */
+/*	$NetBSD: db_interface.c,v 1.79.4.3 2011/03/08 17:29:46 riz Exp $ */
 
 /*
  * Mach Operating System
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.79.4.2 2011/01/16 12:58:24 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.79.4.3 2011/03/08 17:29:46 riz Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -202,6 +202,7 @@
 void db_uvmhistdump(db_expr_t, bool, db_expr_t, const char *);
 #ifdef MULTIPROCESSOR
 void db_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
+void db_xcall_cmd(db_expr_t, bool, db_expr_t, const char *);
 #endif
 void db_page_cmd(db_expr_t, bool, db_expr_t, const char *);
 
@@ -448,7 +449,6 @@
 }
 
 #if defined(MULTIPROCESSOR)
-extern void cpu_debug_dump(void); /* XXX */
 
 void
 db_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
@@ -483,6 +483,12 @@
 	ddb_cpuinfo = ci;
 }
 
+void
+db_xcall_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
+{
+	cpu_xcall_dump();
+}
+
 #endif /* MULTIPROCESSOR */
 
 const struct db_command db_machine_command_table[] = {
@@ -492,6 +498,7 @@
 	{ DDB_ADD_CMD("page",	db_page_cmd,	0,	NULL,NULL,NULL) },
 #ifdef MULTIPROCESSOR
 	{ DDB_ADD_CMD("cpu",	db_cpu_cmd,	0,	NULL,NULL,NULL) },
+	{ DDB_ADD_CMD("xcall",	db_xcall_cmd,	0,	NULL,NULL,NULL) },
 #endif
 	{ DDB_ADD_CMD(NULL,     NULL,           0,NULL,NULL,NULL) }
 };

Index: src/sys/arch/sparc/sparc/genassym.cf
diff -u src/sys/arch/sparc/sparc/genassym.cf:1.56.4.1 src/sys/arch/sparc/sparc/genassym.cf:1.56.4.2
--- src/sys/arch/sparc/sparc/genassym.cf:1.56.4.1	Fri Jan 28 07:16:13 2011
+++ src/sys/arch/sparc/sparc/genassym.cf	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.56.4.1 2011/01/28 07:16:13 snj Exp $
+#	$NetBSD: genassym.cf,v 1.56.4.2 2011/03/08 17:29:46 riz Exp $
 
 #
 # Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -128,6 +128,9 @@
 define	V_INTR		offsetof(struct uvmexp, intrs)
 define	V_SOFT		offsetof(struct uvmexp, softs)
 define	V_FAULTS	offsetof(struct uvmexp, faults)
+define	CPUINFO_LEV14	offsetof(struct cpu_info, ci_sintrcnt[14])
+define	CPUINFO_INTRCNT	offsetof(struct cpu_info, ci_intrcnt)
+define	CPUINFO_SINTRCNT	offsetof(struct cpu_info, ci_sintrcnt)
 define	EV_COUNT	offsetof(struct evcnt, ev_count)
 define	EV_STRUCTSIZE	sizeof(struct evcnt)
 
@@ -161,6 +164,7 @@
 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)
 
 # PTE bits and related information
 define	PG_W		PG_W

Index: src/sys/arch/sparc/sparc/intr.c
diff -u src/sys/arch/sparc/sparc/intr.c:1.100.20.2 src/sys/arch/sparc/sparc/intr.c:1.100.20.3
--- src/sys/arch/sparc/sparc/intr.c:1.100.20.2	Fri Jan 28 07:16:13 2011
+++ src/sys/arch/sparc/sparc/intr.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.100.20.2 2011/01/28 07:16:13 snj Exp $ */
+/*	$NetBSD: intr.c,v 1.100.20.3 2011/03/08 17:29:46 riz Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.100.20.2 2011/01/28 07:16:13 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.100.20.3 2011/03/08 17:29:46 riz Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_sparc_arch.h"
@@ -72,47 +72,7 @@
 
 #if defined(MULTIPROCESSOR)
 void *xcall_cookie;
-
-/* Stats */
-struct evcnt lev13_evcnt = EVCNT_INITIALIZER(EVCNT_TYPE_INTR,0,"xcall","std");
-struct evcnt lev14_evcnt = EVCNT_INITIALIZER(EVCNT_TYPE_INTR,0,"xcall","fast");
-EVCNT_ATTACH_STATIC(lev13_evcnt);
-EVCNT_ATTACH_STATIC(lev14_evcnt);
-#endif
-
-struct evcnt intrcnt[15] = {
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "spur", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev1", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev2", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev3", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev4", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev5", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev6", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev7", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev8", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev9", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "clock", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev11", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev12", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "lev13", "hard"),
-   EVCNT_INITIALIZER(EVCNT_TYPE_INTR, 0, "prof", "hard"),
-};
-
-EVCNT_ATTACH_STATIC2(intrcnt, 0);
-EVCNT_ATTACH_STATIC2(intrcnt, 1);
-EVCNT_ATTACH_STATIC2(intrcnt, 2);
-EVCNT_ATTACH_STATIC2(intrcnt, 3);
-EVCNT_ATTACH_STATIC2(intrcnt, 4);
-EVCNT_ATTACH_STATIC2(intrcnt, 5);
-EVCNT_ATTACH_STATIC2(intrcnt, 6);
-EVCNT_ATTACH_STATIC2(intrcnt, 7);
-EVCNT_ATTACH_STATIC2(intrcnt, 8);
-EVCNT_ATTACH_STATIC2(intrcnt, 9);
-EVCNT_ATTACH_STATIC2(intrcnt, 10);
-EVCNT_ATTACH_STATIC2(intrcnt, 11);
-EVCNT_ATTACH_STATIC2(intrcnt, 12);
-EVCNT_ATTACH_STATIC2(intrcnt, 13);
-EVCNT_ATTACH_STATIC2(intrcnt, 14);
+#endif
 
 void	strayintr(struct clockframe *);
 #ifdef DIAGNOSTIC
@@ -130,6 +90,19 @@
 	static int straytime, nstray;
 	char bits[64];
 	int timesince;
+ 
+#if defined(MULTIPROCESSOR)
+	/*
+	 * XXX
+	 *
+	 * Don't whine about zs interrupts on MP.  We sometimes get
+	 * stray interrupts when polled kernel output on cpu>0 eats
+	 * the interrupt and cpu0 sees it.
+	 */
+#define ZS_INTR_IPL	12
+	if (fp->ipl == ZS_INTR_IPL)
+		return;
+#endif
 
 	printf("stray interrupt cpu%d ipl 0x%x pc=0x%x npc=0x%x psr=%s\n",
 		cpu_number(), fp->ipl, fp->pc, fp->npc,
@@ -229,6 +202,9 @@
 	char bits[64];
 	u_int afsr, afva;
 
+	/* Tally */
+	cpuinfo.ci_intrcnt[15].ev_count++;
+
 	afsr = afva = 0;
 	if ((*cpuinfo.get_asyncflt)(&afsr, &afva) == 0) {
 		printf("Async registers (mid %d): afsr=%s; afva=0x%x%x\n",
@@ -315,6 +291,10 @@
 void
 nmi_soft(struct trapframe *tf)
 {
+
+	/* Tally */
+	cpuinfo.ci_sintrcnt[15].ev_count++;
+
 	if (cpuinfo.mailbox) {
 		/* Check PROM messages */
 		uint8_t msg = *(uint8_t *)cpuinfo.mailbox;
@@ -362,13 +342,19 @@
 #if defined(MULTIPROCESSOR)
 /*
  * Respond to an xcall() request from another CPU.
+ *
+ * This is also called directly from xcall() if we notice an
+ * incoming message while we're waiting to grab the xpmsg_lock.
+ * We pass the address of xcallintr() itself to indicate that
+ * this is not a real interrupt.
  */
-static void
+void
 xcallintr(void *v)
 {
 
 	/* Tally */
-	lev13_evcnt.ev_count++;
+	if (v != xcallintr)
+		cpuinfo.ci_sintrcnt[13].ev_count++;
 
 	/* notyet - cpuinfo.msg.received = 1; */
 	switch (cpuinfo.msg.tag) {

Index: src/sys/arch/sparc/sparc/locore.s
diff -u src/sys/arch/sparc/sparc/locore.s:1.244.8.3 src/sys/arch/sparc/sparc/locore.s:1.244.8.4
--- src/sys/arch/sparc/sparc/locore.s:1.244.8.3	Fri Jan 28 07:16:13 2011
+++ src/sys/arch/sparc/sparc/locore.s	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.s,v 1.244.8.3 2011/01/28 07:16:13 snj Exp $	*/
+/*	$NetBSD: locore.s,v 1.244.8.4 2011/03/08 17:29:46 riz Exp $	*/
 
 /*
  * Copyright (c) 1996 Paul Kranenburg
@@ -1812,6 +1812,7 @@
  */
 
 #if defined(SUN4)
+_ENTRY(memfault_sun4)
 memfault_sun4:
 	TRAP_SETUP(-CCFSZ-80)
 	INCR(_C_LABEL(uvmexp)+V_FAULTS)	! cnt.v_faults++ (clobbers %o0,%o1)
@@ -1876,8 +1877,9 @@
 #endif /* SUN4C || SUN4M */
 #endif /* SUN4 */
 
-memfault_sun4c:
 #if defined(SUN4C)
+_ENTRY(memfault_sun4c)
+memfault_sun4c:
 	TRAP_SETUP(-CCFSZ-80)
 	INCR(_C_LABEL(uvmexp)+V_FAULTS)	! cnt.v_faults++ (clobbers %o0,%o1)
 
@@ -1975,6 +1977,7 @@
 #endif /* SUN4C */
 
 #if defined(SUN4M)
+_ENTRY(memfault_sun4m)
 memfault_sun4m:
 	sethi	%hi(CPUINFO_VA), %l4
 	ld	[%l4 + %lo(CPUINFO_VA+CPUINFO_GETSYNCFLT)], %l5
@@ -2527,13 +2530,15 @@
 	wr	%l4, PSR_ET, %psr	! song and dance is necessary
 	std	%l0, [%sp + CCFSZ + 0]	! set up intrframe/clockframe
 	sll	%l3, 2, %l5
-	set	intrcnt, %l4		! intrcnt[intlev].ev_count++;
+
+	set	CPUINFO_VA + CPUINFO_SINTRCNT, %l4	! sintrcnt[intlev].ev_count++;
 	sll	%l3, EV_STRUCTSHIFT, %o2
 	ldd	[%l4 + %o2], %o0
-	std	%l2, [%sp + CCFSZ + 8]
+	std	%l2, [%sp + CCFSZ + 8]	! set up intrframe/clockframe
 	inccc   %o1
 	addx    %o0, 0, %o0
 	std	%o0, [%l4 + %o2]
+
 	set	_C_LABEL(sintrhand), %l4! %l4 = sintrhand[intlev];
 	ld	[%l4 + %l5], %l4
 
@@ -2681,7 +2686,8 @@
 	wr	%l4, PSR_ET, %psr	! song and dance is necessary
 	std	%l0, [%sp + CCFSZ + 0]	! set up intrframe/clockframe
 	sll	%l3, 2, %l5
-	set	intrcnt, %l4		! intrcnt[intlev].ev_count++;
+
+	set	CPUINFO_VA + CPUINFO_INTRCNT, %l4	! intrcnt[intlev].ev_count++;
 	sll	%l3, EV_STRUCTSHIFT, %o2
 	ldd	[%l4 + %o2], %o0
 	std	%l2, [%sp + CCFSZ + 8]	! set up intrframe/clockframe
@@ -2728,13 +2734,15 @@
 	wr	%l4, PSR_ET, %psr	! song and dance is necessary
 	std	%l0, [%sp + CCFSZ + 0]	! set up intrframe/clockframe
 	sll	%l3, 2, %l5
-	set	intrcnt, %l4		! intrcnt[intlev].ev_count++;
+
+	set	CPUINFO_VA + CPUINFO_INTRCNT, %l4	! intrcnt[intlev].ev_count++;
 	sll	%l3, EV_STRUCTSHIFT, %o2
 	ldd	[%l4 + %o2], %o0
 	std	%l2, [%sp + CCFSZ + 8]	! set up intrframe/clockframe
 	inccc   %o1
 	addx    %o0, 0, %o0
 	std	%o0, [%l4 + %o2]
+
 	set	_C_LABEL(intrhand), %l4	! %l4 = intrhand[intlev];
 	ld	[%l4 + %l5], %l4
 
@@ -2813,11 +2821,11 @@
  * %l6 = &cpuinfo
  */
 lev14_softint:
-	set	_C_LABEL(lev14_evcnt), %l7	! lev14_evcnt.ev_count++;
-	ldd	[%l7 + EV_COUNT], %l4
+	sethi	%hi(CPUINFO_VA), %l7
+	ldd	[%l7 + CPUINFO_LEV14], %l4
 	inccc	%l5
 	addx	%l4, %g0, %l4
-	std	%l4, [%l7 + EV_COUNT]
+	std	%l4, [%l7 + CPUINFO_LEV14]
 
 	ld	[%l6 + CPUINFO_XMSG_TRAP], %l7
 #ifdef DIAGNOSTIC
@@ -3112,7 +3120,7 @@
 
 #if defined(SUN4M)
 _ENTRY(_C_LABEL(nmi_sun4m))
-	INTR_SETUP(-CCFSZ-80)
+	INTR_SETUP(-CCFSZ-80-8-8)	! normal frame, plus g2..g5
 	INCR(_C_LABEL(uvmexp)+V_INTR)	! cnt.v_intr++; (clobbers %o0,%o1)
 
 #if !defined(MSIIEP) /* normal sun4m */
@@ -5904,12 +5912,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
@@ -5928,8 +5953,8 @@
 	 * So we still have to check the blasted QNE bit.
 	 * With any luck it will usually not be set.
 	 */
-	ld	[%o0 + FS_FSR], %o4	! if (f->fs_fsr & QNE)
-	btst	%o5, %o4
+	ld	[%o0 + FS_FSR], %o2	! if (f->fs_fsr & QNE)
+	btst	%o5, %o2
 	bnz	Lfp_storeq		!	goto storeq;
 	 std	%f0, [%o0 + FS_REGS + (4*0)]	! f->fs_f0 = etc;
 Lfp_finish:
@@ -5952,6 +5977,15 @@
 	 std	%f30, [%o0 + FS_REGS + (4*30)]
 
 /*
+ * We got a NULL struct fpstate * on the IPI.  We panic.
+ */
+Lfp_null_fpstate:
+	ld	[%o5 + CPUINFO_CPUNO], %o1
+	sethi	%hi(Lpanic_savefpstate), %o0
+	call	_C_LABEL(panic)
+	 or	%o0, %lo(Lpanic_savefpstate), %o0
+
+/*
  * Store the (now known nonempty) FP queue.
  * We have to reread the fsr each time in order to get the new QNE bit.
  */
@@ -5964,6 +5998,7 @@
 	btst	%o5, %o4
 	bnz	1b
 	 inc	8, %o3
+	st	%o2, [%o0 + FS_FSR]	! fs->fs_fsr = original_fsr
 	b	Lfp_finish		! set qsize and finish storing fregs
 	 srl	%o3, 3, %o3		! (but first fix qsize)
 

Index: src/sys/arch/sparc/sparc/machdep.c
diff -u src/sys/arch/sparc/sparc/machdep.c:1.282.4.3 src/sys/arch/sparc/sparc/machdep.c:1.282.4.4
--- src/sys/arch/sparc/sparc/machdep.c:1.282.4.3	Sun Oct 18 14:40:40 2009
+++ src/sys/arch/sparc/sparc/machdep.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.282.4.3 2009/10/18 14:40:40 bouyer Exp $ */
+/*	$NetBSD: machdep.c,v 1.282.4.4 2011/03/08 17:29:46 riz 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.282.4.3 2009/10/18 14:40:40 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.282.4.4 2011/03/08 17:29:46 riz Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_compat_sunos.h"
@@ -377,7 +377,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/timer.c
diff -u src/sys/arch/sparc/sparc/timer.c:1.23 src/sys/arch/sparc/sparc/timer.c:1.23.28.1
--- src/sys/arch/sparc/sparc/timer.c:1.23	Mon Dec  3 15:34:22 2007
+++ src/sys/arch/sparc/sparc/timer.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: timer.c,v 1.23 2007/12/03 15:34:22 ad Exp $ */
+/*	$NetBSD: timer.c,v 1.23.28.1 2011/03/08 17:29:46 riz Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.23 2007/12/03 15:34:22 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.23.28.1 2011/03/08 17:29:46 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -153,6 +153,7 @@
 timerattach(volatile int *cntreg, volatile int *limreg)
 {
 	u_int prec = 0, t0;
+	void    (*sched_intr_fn)(void *);
 
 	/*
 	 * Calibrate delay() by tweaking the magic constant
@@ -192,11 +193,13 @@
 	cntr.mask = (1 << (31-t0))-1;
 	counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1);
 	
-	printf(": delay constant %d, frequency = %" PRIu64 " Hz\n", timerblurb, counter_timecounter.tc_frequency);
+	printf(": delay constant %d, frequency = %" PRIu64 " Hz\n",
+	       timerblurb, counter_timecounter.tc_frequency);
 
 #if defined(SUN4) || defined(SUN4C)
 	if (CPU_ISSUN4 || CPU_ISSUN4C) {
 		timer_init = timer_init_4;
+		sched_intr_fn = schedintr;
 		level10.ih_fun = clockintr_4;
 		level14.ih_fun = statintr_4;
 		cntr.limit = tmr_ustolim(tick);
@@ -205,6 +208,12 @@
 #if defined(SUN4M)
 	if (CPU_ISSUN4M) {
 		timer_init = timer_init_4m;
+#if defined(MULTIPROCESSOR)
+		if (sparc_ncpus > 1)
+			sched_intr_fn = schedintr_4m;
+		else
+#endif
+			sched_intr_fn = schedintr;
 		level10.ih_fun = clockintr_4m;
 		level14.ih_fun = statintr_4m;
 		cntr.limit = tmr_ustolim4m(tick);
@@ -215,7 +224,7 @@
 	intr_establish(14, 0, &level14, NULL);
 
 	/* Establish a soft interrupt at a lower level for schedclock */
-	sched_cookie = sparc_softintr_establish(IPL_SCHED, schedintr, NULL);
+	sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL);
 	if (sched_cookie == NULL)
 		panic("timerattach: cannot establish schedintr");
 

Index: src/sys/arch/sparc/sparc/timer_sun4m.c
diff -u src/sys/arch/sparc/sparc/timer_sun4m.c:1.16.56.2 src/sys/arch/sparc/sparc/timer_sun4m.c:1.16.56.3
--- src/sys/arch/sparc/sparc/timer_sun4m.c:1.16.56.2	Wed Feb 16 21:33:25 2011
+++ src/sys/arch/sparc/sparc/timer_sun4m.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: timer_sun4m.c,v 1.16.56.2 2011/02/16 21:33:25 bouyer Exp $	*/
+/*	$NetBSD: timer_sun4m.c,v 1.16.56.3 2011/03/08 17:29:46 riz Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.16.56.2 2011/02/16 21:33:25 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.16.56.3 2011/03/08 17:29:46 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -95,6 +95,29 @@
 	icr_si_bic(SINTR_T);
 }
 
+void
+schedintr_4m(void *v)
+{
+
+#ifdef MULTIPROCESSOR
+	/*
+	 * We call hardclock() here so that we make sure it is called on
+	 * all CPUs.  This function ends up being called on sun4m systems
+	 * every tick, so we have avoid 
+	 */
+	if (!CPU_IS_PRIMARY(curcpu()))
+		hardclock(v);
+
+	/*
+	 * The factor 8 is only valid for stathz==100.
+	 * See also clock.c
+	 */
+	if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0)
+#endif
+		schedclock(curlwp);
+}
+
+
 /*
  * Level 10 (clock) interrupts from system counter.
  */
@@ -102,6 +125,7 @@
 clockintr_4m(void *cap)
 {
 
+	KASSERT(CPU_IS_PRIMARY(curcpu()));
 	/*
 	 * XXX this needs to be fixed in a more general way
 	 * problem is that the kernel enables interrupts and THEN
@@ -109,8 +133,10 @@
 	 * a timer interrupt - if we call hardclock() at that point we'll
 	 * panic
 	 * so for now just bail when cold
+	 *
+	 * For MP, we defer calling hardclock() to the schedintr so
+	 * that we call it on all cpus.
 	 */
-	cpuinfo.ci_lev10.ev_count++;
 	if (cold)
 		return 0;
 	/* read the limit register to clear the interrupt */
@@ -129,8 +155,6 @@
 	struct clockframe *frame = cap;
 	u_long newint;
 
-	cpuinfo.ci_lev14.ev_count++;
-
 	/* read the limit register to clear the interrupt */
 	*((volatile int *)&counterreg4m->t_limit);
 
@@ -152,19 +176,23 @@
 	 * The factor 8 is only valid for stathz==100.
 	 * See also clock.c
 	 */
-	if (curlwp && (++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0) {
+#if !defined(MULTIPROCESSOR)
+	if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) {
+#endif
 		if (CLKF_LOPRI(frame, IPL_SCHED)) {
 			/* No need to schedule a soft interrupt */
 			spllowerschedclock();
-			schedintr(cap);
+			schedintr_4m(cap);
 		} else {
 			/*
 			 * We're interrupting a thread that may have the
-			 * scheduler lock; run schedintr() on this CPU later.
+			 * scheduler lock; run schedintr_4m() on this CPU later.
 			 */
 			raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */
 		}
+#if !defined(MULTIPROCESSOR)
 	}
+#endif
 
 	return (1);
 }
@@ -224,13 +252,6 @@
 		cpi->counterreg_4m = (struct counter_4m *)bh;
 	}
 
-	/* Install timer/statclock event counters, per cpu */
-	for (CPU_INFO_FOREACH(n, cpi)) {
-		snprintf(cpi->ci_cpuname, sizeof(cpi->ci_cpuname), "cpu/%d", n);
-		evcnt_attach_dynamic(&cpi->ci_lev10, EVCNT_TYPE_INTR, NULL, cpi->ci_cpuname, "lev10");
-		evcnt_attach_dynamic(&cpi->ci_lev14, EVCNT_TYPE_INTR, NULL, cpi->ci_cpuname, "lev14");
-	}
-
 	/* Put processor counter in "timer" mode */
 	timerreg4m->t_cfg = 0;
 

Index: src/sys/arch/sparc/sparc/timervar.h
diff -u src/sys/arch/sparc/sparc/timervar.h:1.8 src/sys/arch/sparc/sparc/timervar.h:1.8.74.1
--- src/sys/arch/sparc/sparc/timervar.h:1.8	Wed Jun  7 22:38:50 2006
+++ src/sys/arch/sparc/sparc/timervar.h	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: timervar.h,v 1.8 2006/06/07 22:38:50 kardel Exp $	*/
+/*	$NetBSD: timervar.h,v 1.8.74.1 2011/03/08 17:29:46 riz Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -50,6 +50,7 @@
 #endif /* SUN4 || SUN4C */
 
 #if defined(SUN4M)
+void	schedintr_4m(void *);
 int	clockintr_4m(void *);
 int	statintr_4m(void *);
 void	timer_init_4m(void);

Index: src/sys/arch/sparc/sparc/trap.c
diff -u src/sys/arch/sparc/sparc/trap.c:1.176 src/sys/arch/sparc/sparc/trap.c:1.176.4.1
--- src/sys/arch/sparc/sparc/trap.c:1.176	Wed Oct 15 06:51:18 2008
+++ src/sys/arch/sparc/sparc/trap.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.176 2008/10/15 06:51:18 wrstuden Exp $ */
+/*	$NetBSD: trap.c,v 1.176.4.1 2011/03/08 17:29:46 riz Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.176 2008/10/15 06:51:18 wrstuden Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.176.4.1 2011/03/08 17:29:46 riz Exp $");
 
 #include "opt_ddb.h"
 #include "opt_compat_svr4.h"
@@ -479,7 +479,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.95.4.2 src/sys/arch/sparc/sparc/vm_machdep.c:1.95.4.3
--- src/sys/arch/sparc/sparc/vm_machdep.c:1.95.4.2	Sat Jan  9 01:43:51 2010
+++ src/sys/arch/sparc/sparc/vm_machdep.c	Tue Mar  8 17:29:46 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: vm_machdep.c,v 1.95.4.2 2010/01/09 01:43:51 snj Exp $ */
+/*	$NetBSD: vm_machdep.c,v 1.95.4.3 2011/03/08 17:29:46 riz Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.95.4.2 2010/01/09 01:43:51 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.95.4.3 2011/03/08 17:29:46 riz Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_coredump.h"
@@ -230,7 +230,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
 		}
@@ -308,7 +308,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