summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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