Module Name:    src
Committed By:   macallan
Date:           Thu Nov  8 00:34:38 UTC 2012

Modified Files:
        src/sys/arch/sparc64/include: cpu.h ctlreg.h psl.h
        src/sys/arch/sparc64/sparc64: clock.c cpu.c locore.s

Log Message:
use system tick timer instead of %tick on UltraSPARC-III-ish CPUs
review & fixes by Takeshi Nakayama


To generate a diff of this commit:
cvs rdiff -u -r1.98 -r1.99 src/sys/arch/sparc64/include/cpu.h
cvs rdiff -u -r1.56 -r1.57 src/sys/arch/sparc64/include/ctlreg.h
cvs rdiff -u -r1.49 -r1.50 src/sys/arch/sparc64/include/psl.h
cvs rdiff -u -r1.106 -r1.107 src/sys/arch/sparc64/sparc64/clock.c
cvs rdiff -u -r1.102 -r1.103 src/sys/arch/sparc64/sparc64/cpu.c
cvs rdiff -u -r1.341 -r1.342 src/sys/arch/sparc64/sparc64/locore.s

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/sparc64/include/cpu.h
diff -u src/sys/arch/sparc64/include/cpu.h:1.98 src/sys/arch/sparc64/include/cpu.h:1.99
--- src/sys/arch/sparc64/include/cpu.h:1.98	Sat Jul 30 19:29:12 2011
+++ src/sys/arch/sparc64/include/cpu.h	Thu Nov  8 00:34:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.98 2011/07/30 19:29:12 martin Exp $ */
+/*	$NetBSD: cpu.h,v 1.99 2012/11/08 00:34:37 macallan Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -128,7 +128,8 @@ struct cpu_info {
 
 	/* %tick and cpu frequency information */
 	u_long			ci_tick_increment;
-	uint64_t		ci_cpu_clockrate[2];
+	uint64_t		ci_cpu_clockrate[2];	/* %tick */
+	uint64_t		ci_system_clockrate[2];	/* %stick */
 
 	/* Interrupts */
 	struct intrhand		*ci_intrpending[16];
@@ -351,10 +352,12 @@ void *	reserve_dumppages(void *);
 /* clock.c */
 struct timeval;
 int	tickintr(void *);	/* level 10/14 (tick) interrupt code */
+int	stickintr(void *);	/* system tick interrupt code */
 int	clockintr(void *);	/* level 10 (clock) interrupt code */
 int	statintr(void *);	/* level 14 (statclock) interrupt code */
 int	schedintr(void *);	/* level 10 (schedclock) interrupt code */
 void	tickintr_establish(int, int (*)(void *));
+void	stickintr_establish(int, int (*)(void *));
 /* locore.s */
 struct fpstate64;
 void	savefpstate(struct fpstate64 *);
@@ -372,6 +375,10 @@ struct frame *getfp(void);
 void	switchtoctx_us(int);
 void	switchtoctx_usiii(int);
 void	next_tick(long);
+void	next_stick(long);
+void	setstick(long);
+long	getstick(void);
+
 /* trap.c */
 void	cpu_vmspace_exec(struct lwp *, vaddr_t, vaddr_t);
 int	rwindow_save(struct lwp *);

Index: src/sys/arch/sparc64/include/ctlreg.h
diff -u src/sys/arch/sparc64/include/ctlreg.h:1.56 src/sys/arch/sparc64/include/ctlreg.h:1.57
--- src/sys/arch/sparc64/include/ctlreg.h:1.56	Sat Oct  8 08:49:07 2011
+++ src/sys/arch/sparc64/include/ctlreg.h	Thu Nov  8 00:34:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ctlreg.h,v 1.56 2011/10/08 08:49:07 nakayama Exp $ */
+/*	$NetBSD: ctlreg.h,v 1.57 2012/11/08 00:34:37 macallan Exp $ */
 
 /*
  * Copyright (c) 1996-2002 Eduardo Horvath
@@ -415,6 +415,8 @@
 #define	CLEAR_SOFTINT	%asr21	/* Clears these bits */
 #define	SOFTINT		%asr22	/* Reads the register */
 #define	TICK_CMPR	%asr23
+#define	STICK		%asr24
+#define	STICK_CMPR	%asr25
 
 #define	TICK_INT	0x01	/* level-14 clock tick */
 #define	SOFTINT1	(0x1<<1)
@@ -432,6 +434,7 @@
 #define	SOFTINT13	(0x1<<13)
 #define	SOFTINT14	(0x1<<14)
 #define	SOFTINT15	(0x1<<15)
+#define	STICK_INTR	(0x1<<16)	/* system tick */
 
 /* Interrupt Dispatch -- usually reserved for cross-calls */
 #define	ASR_IDSR	0x48 /* Interrupt dispatch status reg */

Index: src/sys/arch/sparc64/include/psl.h
diff -u src/sys/arch/sparc64/include/psl.h:1.49 src/sys/arch/sparc64/include/psl.h:1.50
--- src/sys/arch/sparc64/include/psl.h:1.49	Tue Jul 12 07:51:34 2011
+++ src/sys/arch/sparc64/include/psl.h	Thu Nov  8 00:34:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: psl.h,v 1.49 2011/07/12 07:51:34 mrg Exp $ */
+/*	$NetBSD: psl.h,v 1.50 2012/11/08 00:34:37 macallan Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -330,6 +330,7 @@ SPARC64_GETPR64_DEF(ver)			/* getver() *
 #define GETVER_CPU_IMPL()	((getver() & VER_IMPL) >> VER_IMPL_SHIFT)
 #define GETVER_CPU_MANUF()	((getver() & VER_MANUF) >> VER_MANUF_SHIFT)
 #define CPU_IS_SPITFIRE()	(GETVER_CPU_IMPL() == IMPL_SPITFIRE)
+#define CPU_IS_HUMMINGBIRD()	(GETVER_CPU_IMPL() == IMPL_HUMMINGBIRD)
 #define CPU_IS_USIIIi()		((GETVER_CPU_IMPL() == IMPL_JALAPENO) || \
 				 (GETVER_CPU_IMPL() == IMPL_SERRANO))
 #define CPU_IS_USIII_UP()	(GETVER_CPU_IMPL() >= IMPL_CHEETAH)

Index: src/sys/arch/sparc64/sparc64/clock.c
diff -u src/sys/arch/sparc64/sparc64/clock.c:1.106 src/sys/arch/sparc64/sparc64/clock.c:1.107
--- src/sys/arch/sparc64/sparc64/clock.c:1.106	Sun Sep  4 12:17:46 2011
+++ src/sys/arch/sparc64/sparc64/clock.c	Thu Nov  8 00:34:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: clock.c,v 1.106 2011/09/04 12:17:46 nakayama Exp $ */
+/*	$NetBSD: clock.c,v 1.107 2012/11/08 00:34:38 macallan Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -55,7 +55,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.106 2011/09/04 12:17:46 nakayama Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.107 2012/11/08 00:34:38 macallan Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -99,6 +99,7 @@ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.
  *  counter-timer	 timer#0	 timer#1	 %tick
  *  counter-timer + SMP	 timer#0/%tick	 -		 timer#1 or %tick
  *  no counter-timer	 %tick		 -		 %tick
+ *  US-IIIi		 %stick		 -		 %stick
  */
 
 /*
@@ -137,6 +138,7 @@ void stopcounter(struct timer_4u *);
 int timerblurb = 10; /* Guess a value; used before clock is attached */
 
 static u_int tick_get_timecount(struct timecounter *);
+static u_int stick_get_timecount(struct timecounter *);
 
 /*
  * define timecounter "tick-counter"
@@ -153,6 +155,17 @@ static struct timecounter tick_timecount
 	NULL			/* next timecounter */
 };
 
+static struct timecounter stick_timecounter = {
+	stick_get_timecount,	/* get_timecount */
+	0,			/* no poll_pps */
+	~0u,			/* counter_mask */
+	0,                      /* frequency - set at initialisation */
+	"stick-counter",	/* name */
+	100,			/* quality */
+	0,			/* private reference - UNUSED */
+	NULL			/* next timecounter */
+};
+
 /*
  * tick_get_timecount provide current tick counter value
  */
@@ -162,6 +175,12 @@ tick_get_timecount(struct timecounter *t
 	return cpu_counter();
 }
 
+static u_int
+stick_get_timecount(struct timecounter *tc)
+{
+	return getstick();
+}
+
 #ifdef MULTIPROCESSOR
 static u_int counter_get_timecount(struct timecounter *);
 
@@ -329,6 +348,27 @@ tickintr_establish(int pil, int (*fun)(v
 	intr_restore(s);
 }
 
+void
+stickintr_establish(int pil, int (*fun)(void *))
+{
+	int s;
+	struct intrhand *ih;
+	struct cpu_info *ci = curcpu();
+
+	ih = sparc_softintr_establish(pil, fun, NULL);
+	ih->ih_number = 1;
+	if (CPU_IS_PRIMARY(ci))
+		intr_establish(pil, true, ih);
+	ci->ci_tick_ih = ih;
+
+	/* set the next interrupt time */
+	ci->ci_tick_increment = ci->ci_system_clockrate[0] / hz;
+
+	s = intr_disable();
+	next_stick(ci->ci_tick_increment);
+	intr_restore(s);
+}
+
 /*
  * Set up the real-time and statistics clocks.  Leave stathz 0 only if
  * no alternative timer is available.
@@ -338,6 +378,7 @@ tickintr_establish(int pil, int (*fun)(v
 void
 cpu_initclocks(void)
 {
+	struct cpu_info *ci = curcpu();
 #ifndef MULTIPROCESSOR
 	int statint, minint;
 #endif
@@ -361,17 +402,24 @@ cpu_initclocks(void)
 	}
 
 	/* Make sure we have a sane cpu_clockrate -- we'll need it */
-	if (!curcpu()->ci_cpu_clockrate[0]) {
+	if (!ci->ci_cpu_clockrate[0]) {
 		/* Default to 200MHz clock XXXXX */
-		curcpu()->ci_cpu_clockrate[0] = 200000000;
-		curcpu()->ci_cpu_clockrate[1] = 200000000 / 1000000;
+		ci->ci_cpu_clockrate[0] = 200000000;
+		ci->ci_cpu_clockrate[1] = 200000000 / 1000000;
 	}
 
 	/* Initialize the %tick register */
 	settick(0);
 
-	tick_timecounter.tc_frequency = curcpu()->ci_cpu_clockrate[0];
-	tc_init(&tick_timecounter);
+	if (ci->ci_system_clockrate[0] == 0) {
+		tick_timecounter.tc_frequency = ci->ci_cpu_clockrate[0];
+		tc_init(&tick_timecounter);
+	} else {
+		setstick(0);
+		stick_timecounter.tc_frequency = 
+		    ci->ci_system_clockrate[0];
+		tc_init(&stick_timecounter);
+	}
 
 	/*
 	 * Now handle machines w/o counter-timers.
@@ -379,13 +427,21 @@ cpu_initclocks(void)
 
 	if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) {
 
-		aprint_normal("No counter-timer -- using %%tick at %luMHz as "
-			"system clock.\n",
-			(unsigned long)curcpu()->ci_cpu_clockrate[1]);
-
-		/* We don't have a counter-timer -- use %tick */
-		tickintr_establish(PIL_CLOCK, tickintr);
+		if (ci->ci_system_clockrate[0] == 0) {
+			aprint_normal("No counter-timer -- using %%tick "
+			    "at %luMHz as system clock.\n",
+			    (unsigned long)ci->ci_cpu_clockrate[1]);
+
+			/* We don't have a counter-timer -- use %tick */
+			tickintr_establish(PIL_CLOCK, tickintr);
+		} else {
+			aprint_normal("No counter-timer -- using %%stick "
+			    "at %luMHz as system clock.\n",
+			    (unsigned long)ci->ci_system_clockrate[1]);
 
+			/* We don't have a counter-timer -- use %stick */
+			stickintr_establish(PIL_CLOCK, stickintr);
+		}
 		/* We only have one timer so we have no statclock */
 		stathz = 0;
 
@@ -525,6 +581,22 @@ tickintr(void *cap)
 	return (1);
 }
 
+int
+stickintr(void *cap)
+{
+	int s;
+
+	hardclock((struct clockframe *)cap);
+
+	s = intr_disable();
+	/* Reset the interrupt */
+	next_stick(curcpu()->ci_tick_increment);
+	intr_restore(s);
+	curcpu()->ci_tick_evcnt.ev_count++;
+
+	return (1);
+}
+
 #ifndef MULTIPROCESSOR
 /*
  * Level 14 (stat clock) interrupt handler.

Index: src/sys/arch/sparc64/sparc64/cpu.c
diff -u src/sys/arch/sparc64/sparc64/cpu.c:1.102 src/sys/arch/sparc64/sparc64/cpu.c:1.103
--- src/sys/arch/sparc64/sparc64/cpu.c:1.102	Sat Oct 27 17:18:12 2012
+++ src/sys/arch/sparc64/sparc64/cpu.c	Thu Nov  8 00:34:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.102 2012/10/27 17:18:12 chs Exp $ */
+/*	$NetBSD: cpu.c,v 1.103 2012/11/08 00:34:38 macallan Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.102 2012/10/27 17:18:12 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.103 2012/11/08 00:34:38 macallan Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -242,7 +242,7 @@ void
 cpu_attach(device_t parent, device_t dev, void *aux)
 {
 	int node;
-	long clk;
+	long clk, sclk = 0;
 	struct mainbus_attach_args *ma = aux;
 	struct cpu_info *ci;
 	const char *sep;
@@ -299,12 +299,23 @@ cpu_attach(device_t parent, device_t dev
 		ci->ci_cpu_clockrate[1] = clk / 1000000;
 	}
 
+	if (!CPU_IS_HUMMINGBIRD()) {
+		sclk = prom_getpropint(findroot(), "stick-frequency", 0);
+	}
+	ci->ci_system_clockrate[0] = sclk;
+	ci->ci_system_clockrate[1] = sclk / 1000000;
+
 	snprintf(buf, sizeof buf, "%s @ %s MHz",
 		prom_getpropstring(node, "name"), clockfreq(clk));
 	snprintf(cpu_model, sizeof cpu_model, "%s (%s)", machine_model, buf);
 
 	aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid);
 	aprint_naive("\n");
+
+	if (ci->ci_system_clockrate[0] != 0) {
+		aprint_normal_dev(dev, "system tick frequency %d MHz\n", 
+		    (int)ci->ci_system_clockrate[1]);
+	}
 	aprint_normal_dev(dev, "");
 
 	bigcache = 0;
@@ -452,6 +463,8 @@ cpu_boot_secondary_processors(void)
 		sync_tick = 1;
 		membar_Sync();
 		settick(0);
+		if (ci->ci_system_clockrate[0] != 0)
+			setstick(0);
 
 		setpstate(pstate);
 
@@ -480,8 +493,12 @@ cpu_hatch(void)
 		/* we do nothing here */
 	}
 	settick(0);
-
-	tickintr_establish(PIL_CLOCK, tickintr);
+	if (curcpu()->ci_system_clockrate[0] != 0) {
+		setstick(0);
+		stickintr_establish(PIL_CLOCK, stickintr);
+	} else {
+		tickintr_establish(PIL_CLOCK, tickintr);
+	}
 	spl0();
 }
 #endif /* MULTIPROCESSOR */

Index: src/sys/arch/sparc64/sparc64/locore.s
diff -u src/sys/arch/sparc64/sparc64/locore.s:1.341 src/sys/arch/sparc64/sparc64/locore.s:1.342
--- src/sys/arch/sparc64/sparc64/locore.s:1.341	Sat Mar 17 22:19:53 2012
+++ src/sys/arch/sparc64/sparc64/locore.s	Thu Nov  8 00:34:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.s,v 1.341 2012/03/17 22:19:53 mrg Exp $	*/
+/*	$NetBSD: locore.s,v 1.342 2012/11/08 00:34:38 macallan Exp $	*/
 
 /*
  * Copyright (c) 2006-2010 Matthew R. Green
@@ -3270,13 +3270,16 @@ ENTRY_NOPROFILE(sparc_interrupt)
 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
 #endif
 	/*
-	 * If this is a %tick softint, clear it then call interrupt_vector.
+	 * If this is a %tick or %stick softint, clear it then call
+	 * interrupt_vector. Only one of them should be enabled at any given
+	 * time.
 	 */
 	rd	SOFTINT, %g1
-	btst	1, %g1
+	set	0x10001, %g5
+	andcc	%g5, %g1, %g5
 	bz,pt	%icc, 0f
 	 sethi	%hi(CPUINFO_VA+CI_TICK_IH), %g3
-	wr	%g0, 1, CLEAR_SOFTINT
+	wr	%g0, %g5, CLEAR_SOFTINT
 	ba,pt	%icc, setup_sparcintr
 	 LDPTR	[%g3 + %lo(CPUINFO_VA+CI_TICK_IH)], %g5
 0:
@@ -6058,6 +6061,77 @@ Ltick_ovflw:
 	 wr	%o2, TICK_CMPR
 #endif
 
+/*
+ * setstick(long)
+ */
+ENTRY(setstick)
+	retl
+	 wr %o0, STICK
+
+/*
+ * long getstick(void)
+ */
+ENTRY(getstick)
+	retl
+	 rd STICK, %o0
+
+/*
+ * next_stick(long increment)
+ *
+ * Sets the %stick_cmpr register to fire off in `increment' machine
+ * cycles in the future.  Also handles %stick wraparound.  In 32-bit
+ * mode we're limited to a 32-bit increment.
+ */
+ENTRY(next_stick)
+	rd	STICK_CMPR, %o2
+	rd	STICK, %o1
+
+	mov	1, %o3		! Mask off high bits of these registers
+	sllx	%o3, 63, %o3
+	andn	%o1, %o3, %o1
+	andn	%o2, %o3, %o2
+	cmp	%o1, %o2	! Did we wrap?  (tick < tick_cmpr)
+	bgt,pt	%icc, 1f
+	 add	%o1, 1000, %o1	! Need some slack so we don't lose intrs.
+
+	/*
+	 * Handle the unlikely case of %stick wrapping.
+	 *
+	 * This should only happen every 10 years or more.
+	 *
+	 * We need to increment the time base by the size of %stick in
+	 * microseconds.  This will require some divides and multiplies
+	 * which can take time.  So we re-read %stick.
+	 *
+	 */
+
+	/* XXXXX NOT IMPLEMENTED */
+
+
+
+1:
+	add	%o2, %o0, %o2
+	andn	%o2, %o3, %o4
+	brlz,pn	%o4, Lstick_ovflw
+	 cmp	%o2, %o1	! Has this stick passed?
+	blt,pn	%xcc, 1b	! Yes
+	 nop
+	retl
+	 wr	%o2, STICK_CMPR
+
+Lstick_ovflw:
+/*
+ * When we get here tick_cmpr has wrapped, but we don't know if %stick
+ * has wrapped.  If bit 62 is set then we have not wrapped and we can
+ * use the current value of %o4 as %stick.  Otherwise we need to return
+ * to our loop with %o4 as %stick_cmpr (%o2).
+ */
+	srlx	%o3, 1, %o5
+	btst	%o5, %o1
+	bz,pn	%xcc, 1b
+	 mov	%o4, %o2
+	retl
+	 wr	%o2, STICK_CMPR
 
 ENTRY(setjmp)
 	save	%sp, -CC64FSZ, %sp	! Need a frame to return to.

Reply via email to