From 33f12b1200fdafb8045b06f87690bc3baa7fc971 Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Sat, 20 Sep 2008 11:26:13 +0000 Subject: [PATCH] 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 --- sys/sparc64/include/tick.h | 2 ++ sys/sparc64/sparc64/mp_machdep.c | 2 ++ sys/sparc64/sparc64/tick.c | 58 ++++++++++++++++---------------- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/sys/sparc64/include/tick.h b/sys/sparc64/include/tick.h index 456e9f037ba..9182cb405b5 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 3f372ca1ba9..5cace4817f7 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 612ff34387f..97472286168 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; @@ -204,6 +188,22 @@ tick_hardclock(struct trapframe *tf) u_long adj, tick; register_t s; + critical_enter(); + 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();