Module Name: src
Committed By: riz
Date: Fri Nov 23 16:12:36 UTC 2012
Modified Files:
src/sys/arch/sparc64/include [netbsd-6]: cpu.h ctlreg.h psl.h
src/sys/arch/sparc64/sparc64 [netbsd-6]: clock.c cpu.c locore.s
Log Message:
Pull up following revision(s) (requested by macallan in ticket #695):
sys/arch/sparc64/include/cpu.h: revision 1.99
sys/arch/sparc64/sparc64/cpu.c: revision 1.103
sys/arch/sparc64/include/psl.h: revision 1.50
sys/arch/sparc64/sparc64/clock.c: revision 1.107
sys/arch/sparc64/include/ctlreg.h: revision 1.57
sys/arch/sparc64/sparc64/locore.s: revision 1.342
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.98.8.1 src/sys/arch/sparc64/include/cpu.h
cvs rdiff -u -r1.56 -r1.56.8.1 src/sys/arch/sparc64/include/ctlreg.h
cvs rdiff -u -r1.49 -r1.49.8.1 src/sys/arch/sparc64/include/psl.h
cvs rdiff -u -r1.106 -r1.106.8.1 src/sys/arch/sparc64/sparc64/clock.c
cvs rdiff -u -r1.101 -r1.101.8.1 src/sys/arch/sparc64/sparc64/cpu.c
cvs rdiff -u -r1.338.8.2 -r1.338.8.3 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.98.8.1
--- src/sys/arch/sparc64/include/cpu.h:1.98 Sat Jul 30 19:29:12 2011
+++ src/sys/arch/sparc64/include/cpu.h Fri Nov 23 16:12:35 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.98 2011/07/30 19:29:12 martin Exp $ */
+/* $NetBSD: cpu.h,v 1.98.8.1 2012/11/23 16:12:35 riz 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.56.8.1
--- src/sys/arch/sparc64/include/ctlreg.h:1.56 Sat Oct 8 08:49:07 2011
+++ src/sys/arch/sparc64/include/ctlreg.h Fri Nov 23 16:12:36 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ctlreg.h,v 1.56 2011/10/08 08:49:07 nakayama Exp $ */
+/* $NetBSD: ctlreg.h,v 1.56.8.1 2012/11/23 16:12:36 riz 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.49.8.1
--- src/sys/arch/sparc64/include/psl.h:1.49 Tue Jul 12 07:51:34 2011
+++ src/sys/arch/sparc64/include/psl.h Fri Nov 23 16:12:35 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: psl.h,v 1.49 2011/07/12 07:51:34 mrg Exp $ */
+/* $NetBSD: psl.h,v 1.49.8.1 2012/11/23 16:12:35 riz 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.106.8.1
--- src/sys/arch/sparc64/sparc64/clock.c:1.106 Sun Sep 4 12:17:46 2011
+++ src/sys/arch/sparc64/sparc64/clock.c Fri Nov 23 16:12:36 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: clock.c,v 1.106 2011/09/04 12:17:46 nakayama Exp $ */
+/* $NetBSD: clock.c,v 1.106.8.1 2012/11/23 16:12:36 riz 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.106.8.1 2012/11/23 16:12:36 riz 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.101 src/sys/arch/sparc64/sparc64/cpu.c:1.101.8.1
--- src/sys/arch/sparc64/sparc64/cpu.c:1.101 Sat Oct 8 08:49:07 2011
+++ src/sys/arch/sparc64/sparc64/cpu.c Fri Nov 23 16:12:36 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.101 2011/10/08 08:49:07 nakayama Exp $ */
+/* $NetBSD: cpu.c,v 1.101.8.1 2012/11/23 16:12:36 riz Exp $ */
/*
* Copyright (c) 1996
@@ -52,7 +52,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.101 2011/10/08 08:49:07 nakayama Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.101.8.1 2012/11/23 16:12:36 riz Exp $");
#include "opt_multiprocessor.h"
@@ -242,7 +242,7 @@ void
cpu_attach(struct device *parent, struct device *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(struct device *parent, struct
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.338.8.2 src/sys/arch/sparc64/sparc64/locore.s:1.338.8.3
--- src/sys/arch/sparc64/sparc64/locore.s:1.338.8.2 Wed Mar 21 16:10:21 2012
+++ src/sys/arch/sparc64/sparc64/locore.s Fri Nov 23 16:12:36 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.s,v 1.338.8.2 2012/03/21 16:10:21 riz Exp $ */
+/* $NetBSD: locore.s,v 1.338.8.3 2012/11/23 16:12:36 riz 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:
@@ -6068,6 +6071,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.