Module Name:    src
Committed By:   mrg
Date:           Sun Jan 19 00:22:33 UTC 2014

Modified Files:
        src/sys/arch/sparc/sparc: timer.c timer_sun4m.c timervar.h

Log Message:
remove schedintr_4m(), and go back to only having the level 14
timer call statclock/schedclock.  the randomness for this clock
makes the hardclock() call very jittery.

instead of this, trigger a softintr IPI at level 10 on non-primary
CPUs from the primary CPU's clock interrupt (at level 10.)  this
cleans up the generic sparc timer code a little as well.

this makes the time goes backwards problem *much* less frequent,
but i still see it sometimes.


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/arch/sparc/sparc/timer.c
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/sparc/sparc/timer_sun4m.c
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/sparc/sparc/timervar.h

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/sparc/timer.c
diff -u src/sys/arch/sparc/sparc/timer.c:1.31 src/sys/arch/sparc/sparc/timer.c:1.32
--- src/sys/arch/sparc/sparc/timer.c:1.31	Sat Oct 19 19:40:23 2013
+++ src/sys/arch/sparc/sparc/timer.c	Sun Jan 19 00:22:33 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: timer.c,v 1.31 2013/10/19 19:40:23 mrg Exp $ */
+/*	$NetBSD: timer.c,v 1.32 2014/01/19 00:22:33 mrg Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.31 2013/10/19 19:40:23 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.32 2014/01/19 00:22:33 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -87,7 +87,7 @@ void *sched_cookie;
 static struct counter {
 	volatile u_int *cntreg;	/* counter register */
 	u_int limit;		/* limit we count up to */
-	u_int offset;		/* accumulated offet due to wraps */
+	u_int offset;		/* accumulated offset due to wraps */
 	u_int shift;		/* scaling for valid bits */
 	u_int mask;		/* valid bit mask */
 } cntr;
@@ -117,12 +117,11 @@ timer_get_timecount(struct timecounter *
 	u_int c, res, r;
 	int s;
 
-
 	s = splhigh();
 
 	res = c = *ctr->cntreg;
 
-	res  &= ~TMR_LIMIT;
+	res &= ~TMR_LIMIT;
 
 	if (c != res) {
 		r = ctr->limit;
@@ -155,7 +154,6 @@ void
 timerattach(volatile int *cntreg, volatile int *limreg)
 {
 	u_int prec = 0, t0;
-	void    (*sched_intr_fn)(void *);
 
 	/*
 	 * Calibrate delay() by tweaking the magic constant
@@ -198,11 +196,11 @@ timerattach(volatile int *cntreg, volati
 	
 	printf(": delay constant %d, frequency = %" PRIu64 " Hz\n",
 	       timerblurb, counter_timecounter.tc_frequency);
+printf("timer: limit %u shift %u mask %x\n", cntr.limit, cntr.shift, cntr.mask);
 
 #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);
@@ -211,12 +209,6 @@ timerattach(volatile int *cntreg, volati
 #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);
@@ -227,7 +219,7 @@ timerattach(volatile int *cntreg, volati
 	intr_establish(14, 0, &level14, NULL, true);
 
 	/* Establish a soft interrupt at a lower level for schedclock */
-	sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL);
+	sched_cookie = sparc_softintr_establish(IPL_SCHED, schedintr, 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.29 src/sys/arch/sparc/sparc/timer_sun4m.c:1.30
--- src/sys/arch/sparc/sparc/timer_sun4m.c:1.29	Sat Nov 16 23:54:01 2013
+++ src/sys/arch/sparc/sparc/timer_sun4m.c	Sun Jan 19 00:22:33 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: timer_sun4m.c,v 1.29 2013/11/16 23:54:01 mrg Exp $	*/
+/*	$NetBSD: timer_sun4m.c,v 1.30 2014/01/19 00:22:33 mrg Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.29 2013/11/16 23:54:01 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.30 2014/01/19 00:22:33 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -78,6 +78,11 @@ struct timer_4m		*timerreg4m;
 #define	counterreg4m	cpuinfo.counterreg_4m
 
 /*
+ * SMP hardclock handler.
+ */
+#define IPL_HARDCLOCK	10
+
+/*
  * Set up the real-time and statistics clocks.
  * Leave stathz 0 only if no alternative timer is available.
  *
@@ -96,31 +101,45 @@ timer_init_4m(void)
 	icr_si_bic(SINTR_T);
 }
 
-void
-schedintr_4m(void *v)
+#ifdef MULTIPROCESSOR
+/*
+ * Handle SMP hardclock() calling for this CPU.
+ */
+static void
+hardclock_ipi(void *cap)
 {
+	int s = splsched();
 
-	kpreempt_disable();
+	hardclock((struct clockframe *)cap);
+	splx(s);
+}
+#endif
+
+/*
+ * Call hardclock on all CPUs.
+ */
+static void
+handle_hardclock(struct clockframe *cap)
+{
+	int s;
 #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.
-	 */
-	if (!CPU_IS_PRIMARY(curcpu()))
-		hardclock(v);
+	struct cpu_info *cpi;
+	CPU_INFO_ITERATOR n;
 
-	/*
-	 * The factor 8 is only valid for stathz==100.
-	 * See also clock.c
-	 */
-	if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0)
+	for (CPU_INFO_FOREACH(n, cpi)) {
+		if (cpi == cpuinfo.ci_self) {
+			KASSERT(CPU_IS_PRIMARY(cpi));
+			continue;
+		}
+		
+		raise_ipi(cpi, IPL_HARDCLOCK);
+	}
 #endif
-		schedclock(curlwp);
-	kpreempt_enable();
+	s = splsched();
+	hardclock(cap);
+	splx(s);
 }
 
-
 /*
  * Level 10 (clock) interrupts from system counter.
  */
@@ -128,7 +147,6 @@ int
 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
@@ -146,7 +164,14 @@ clockintr_4m(void *cap)
 	/* read the limit register to clear the interrupt */
 	*((volatile int *)&timerreg4m->t_limit);
 	tickle_tc();
-	hardclock((struct clockframe *)cap);
+
+	/*
+	 * We don't have a system-clock per-cpu, and we'd like to keep
+	 * the per-cpu timer for the statclock, so, send an IPI to
+	 * everyone to call hardclock.
+	 */
+	handle_hardclock(cap);
+
 	kpreempt_enable();
 	return (1);
 }
@@ -183,23 +208,19 @@ statintr_4m(void *cap)
 	 * The factor 8 is only valid for stathz==100.
 	 * See also clock.c
 	 */
-#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_4m(cap);
+			schedintr(cap);
 		} else {
 			/*
 			 * We're interrupting a thread that may have the
-			 * scheduler lock; run schedintr_4m() on this CPU later.
+			 * scheduler lock; run schedintr() on this CPU later.
 			 */
 			raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */
 		}
-#if !defined(MULTIPROCESSOR)
 	}
-#endif
 	kpreempt_enable();
 
 	return (1);
@@ -261,6 +282,22 @@ timerattach_obio_4m(device_t parent, dev
 		cpi->counterreg_4m = (struct counter_4m *)bh;
 	}
 
+#if defined(MULTIPROCESSOR)
+	if (sparc_ncpus > 1) {
+		/*
+		 * Note that we don't actually use this cookie after checking
+		 * it was establised, we call directly via raise_ipi() on
+		 * IPL_HARDCLOCK.
+		 */
+		void *hardclock_cookie;
+
+		hardclock_cookie = sparc_softintr_establish(IPL_HARDCLOCK,
+		    hardclock_ipi, NULL);
+		if (hardclock_cookie == NULL)
+			panic("timerattach: cannot establish hardclock_intr");
+	}
+#endif
+
 	/* 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.11 src/sys/arch/sparc/sparc/timervar.h:1.12
--- src/sys/arch/sparc/sparc/timervar.h:1.11	Sun Jul 29 00:04:05 2012
+++ src/sys/arch/sparc/sparc/timervar.h	Sun Jan 19 00:22:33 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: timervar.h,v 1.11 2012/07/29 00:04:05 matt Exp $	*/
+/*	$NetBSD: timervar.h,v 1.12 2014/01/19 00:22:33 mrg Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -50,7 +50,6 @@ void	timerattach_mainbus_4c(device_t, de
 #endif /* SUN4 || SUN4C */
 
 #if defined(SUN4M)
-void	schedintr_4m(void *);
 int	clockintr_4m(void *);
 int	statintr_4m(void *);
 void	timer_init_4m(void);
@@ -66,7 +65,7 @@ extern void tickle_tc(void);
 
 /* Common timer attach routine in timer.c: */
 void	timerattach(volatile int *, volatile int *);
-extern void	*sched_cookie;	/* for schedclock() interrupts */
+extern void	*sched_cookie;		/* for schedclock() interrupts */
 
 static inline u_long __attribute__((__unused__))
 new_interval(void)

Reply via email to