diff options
-rw-r--r-- | sys/sparc64/include/tick.h | 2 | ||||
-rw-r--r-- | sys/sparc64/sparc64/mp_machdep.c | 2 | ||||
-rw-r--r-- | 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 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); |