summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2008-09-20 11:26:13 +0000
committermarius <marius@FreeBSD.org>2008-09-20 11:26:13 +0000
commit5f0e19e7dfea53f7e3b21d64021a42f35ee2d45f (patch)
tree9ef9ad76901e61f27dc1e4f8731ee4f7a1f4cc9a /sys/sparc64
parent12843f93b9d7372b583e0d4102c840304cc73fca (diff)
downloadFreeBSD-src-5f0e19e7dfea53f7e3b21d64021a42f35ee2d45f.zip
FreeBSD-src-5f0e19e7dfea53f7e3b21d64021a42f35ee2d45f.tar.gz
Use the STICK timers only when absolutely necessary, i.e. if a machine
consists of CPUs running at different speeds, for driving hardclock as these timers in turn are driven at frequencies as low as 5MHz, resulting in bad granularity compared to the TICK timers. However, don't employ the workaround for the BlackBird erratum #1 when using the TICK timer on machines with cheetah-class CPUs for performance reasons. Reported by: Florian Smeets
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/include/tick.h2
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c2
-rw-r--r--sys/sparc64/sparc64/tick.c58
3 files changed, 33 insertions, 29 deletions
diff --git a/sys/sparc64/include/tick.h b/sys/sparc64/include/tick.h
index 456e9f0..9182cb4 100644
--- a/sys/sparc64/include/tick.h
+++ b/sys/sparc64/include/tick.h
@@ -29,6 +29,8 @@
#ifndef _MACHINE_TICK_H_
#define _MACHINE_TICK_H_
+extern u_int hardclock_use_stick;
+
void tick_clear(void);
void tick_start(void);
void tick_stop(void);
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index 3f372ca..5cace48 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -285,6 +285,8 @@ cpu_mp_start(void)
if (OF_getprop(child, "clock-frequency", &clock,
sizeof(clock)) <= 0)
panic("%s: can't get clock", __func__);
+ if (clock != PCPU_GET(clock))
+ hardclock_use_stick = 1;
csa->csa_state = 0;
sun4u_startcpu(child, (void *)mp_tramp, 0);
diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c
index 612ff34..9747228 100644
--- a/sys/sparc64/sparc64/tick.c
+++ b/sys/sparc64/sparc64/tick.c
@@ -72,9 +72,12 @@ static int adjust_ticks = 0;
SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_ticks, CTLFLAG_RD, &adjust_ticks,
0, "total number of tick interrupts with adjustment");
+u_int hardclock_use_stick = 0;
+SYSCTL_INT(_machdep_tick, OID_AUTO, hardclock_use_stick, CTLFLAG_RD,
+ &hardclock_use_stick, 0, "hardclock uses STICK instead of TICK timer");
+
static struct timecounter tick_tc;
static u_long tick_increment;
-static u_int hardclock_use_stick;
static uint64_t tick_cputicks(void);
static timecounter_get_t tick_get_timecount_up;
@@ -82,6 +85,7 @@ static timecounter_get_t tick_get_timecount_up;
static timecounter_get_t tick_get_timecount_mp;
#endif
static void tick_hardclock(struct trapframe *tf);
+static void tick_hardclock_bbwar(struct trapframe *tf);
static inline void tick_hardclock_common(struct trapframe *tf, u_long tick,
u_long adj);
static inline void tick_process(struct trapframe *tf);
@@ -102,42 +106,22 @@ cpu_initclocks(void)
stathz = hz;
/*
- * On USIII and later we use the STICK timer instead of the TICK
- * one if possible in order to ensure hardclock is driven by same
- * frequency on all CPUs (besides, we no longer need to apply the
- * workaround for the BlackBird erratum #1 there). Similarly, we
- * don't provide a CPU ticker in that case as long as we can't
- * specify the ticker frequency per CPU.
- * XXX we don't use the STICK timer with all CPUs beyond USIII
- * unconditionally, yet, due to unsolved problems with USIIIi APs
- * causing a hang when using it.
+ * Given that the STICK timers typically are driven at rather low
+ * frequencies they shouldn't be used except when really necessary.
*/
- switch (cpu_impl) {
- case CPU_IMPL_ULTRASPARCIII: /* mandatory */
- case CPU_IMPL_ULTRASPARCIIIp:
- hardclock_use_stick = 1;
- break;
- case CPU_IMPL_ULTRASPARCIIIi:
-#ifdef SMP
- if (cpu_mp_probe() == 0) {
-#endif
- hardclock_use_stick = 1;
- break;
-#ifdef SMP
- }
- /* FALLTHROUGH */
-#endif
- default:
- hardclock_use_stick = 0;
- }
if (hardclock_use_stick != 0) {
if (OF_getprop(OF_parent(PCPU_GET(node)), "stick-frequency",
&clock, sizeof(clock)) == -1)
panic("%s: could not determine STICK frequency", __func__);
intr_setup(PIL_TICK, stick_hardclock, -1, NULL, NULL);
+ /*
+ * We don't provide a CPU ticker as long as the frequency
+ * supplied isn't actually used per-CPU.
+ */
} else {
clock = PCPU_GET(clock);
- intr_setup(PIL_TICK, tick_hardclock, -1, NULL, NULL);
+ intr_setup(PIL_TICK, cpu_impl < CPU_IMPL_ULTRASPARCIII ?
+ tick_hardclock_bbwar : tick_hardclock, -1, NULL, NULL);
set_cputicker(tick_cputicks, clock, 0);
}
tick_increment = clock / hz;
@@ -208,6 +192,22 @@ tick_hardclock(struct trapframe *tf)
adj = PCPU_GET(tickadj);
s = intr_disable();
tick = rd(tick);
+ wr(tick_cmpr, tick + tick_increment - adj, 0);
+ intr_restore(s);
+ tick_hardclock_common(tf, tick, adj);
+ critical_exit();
+}
+
+static void
+tick_hardclock_bbwar(struct trapframe *tf)
+{
+ u_long adj, tick;
+ register_t s;
+
+ critical_enter();
+ adj = PCPU_GET(tickadj);
+ s = intr_disable();
+ tick = rd(tick);
wrtickcmpr(tick + tick_increment - adj, 0);
intr_restore(s);
tick_hardclock_common(tf, tick, adj);
OpenPOWER on IntegriCloud