diff options
author | marius <marius@FreeBSD.org> | 2005-04-16 14:57:38 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2005-04-16 14:57:38 +0000 |
commit | fe74973b3947717b73a1df5e1e8b073e53ff3d86 (patch) | |
tree | 91862a3a1c8f4523c5187cef8726bea0da9e1f6a /sys/sparc64/include | |
parent | f6ff285bc8587aaf4f40794b74acb98f6222a997 (diff) | |
download | FreeBSD-src-fe74973b3947717b73a1df5e1e8b073e53ff3d86.zip FreeBSD-src-fe74973b3947717b73a1df5e1e8b073e53ff3d86.tar.gz |
- Add a workaround for a bug in BlackBird CPUs (said to be part of the
SpitFire erratum #54) which can cause writes to the TICK_CMPR register
to fail. This seems to fix the dying clocks problem reported by jhb@
and kris@. [1]
- In tick_start() don't reset the tick counter of the boot processor to
zero. It's initially reset in _start() and afterwards but _before_
tick_start() is called on the BSP the APs synchronise with the tick
counter of the BSP in mp_startup(). Resetting the tick counter of the
BSP in tick_start() probably also was the cause of problems seen when
using the CPU tick counter as timecounter on SMP machines.
Not resetting the tick counter of the BSP in mp_startup() makes the
tick counters and tick interrupts between the BSP and APs be pretty
much in sync as it's supposed to be. This also means there's no longer
a real reason to have separate tick_start() and tick_start_ap() so
merge them and zap tick_start_ap(). This is also a first step in
simplifying the interface to the tick counters in preparation to use
alternate clock hardware where available.
- Switch to the algorithm used on FreeBSD/ia64 for updating the tick
interrupt register and which compensates the clock drift caused by
varying delays between when the tick interrupts actually trigger and
when they are serviced. Not compensating the clock drift mainly hurts
interactive performance especially when using WITNESS. [2]
For further information about the algorithm also see the commit log
of sys/ia64/ia64/interrupt.c rev. 1.38.
On sparc64 the sysctls for monitoring the behaviour of the tick
interrupts are machdep.tick.adjust_edges, machdep.tick.adjust_excess,
machdep.tick.adjust_missed and machdep.tick.adjust_ticks.
- In tick_init() just use tick_stop() for stopping the tick interrupts
until a proper handler is set up later. This also stops the system
tick interrupt on USIII systems earlier.
- In tick_start() check for a rough upper limit of HZ.
- Some minor changes, e.g. use FBSDID, remove unused headers, etc.
Info obtained from: Linux [1]
Ok'ed by: marcel [2]
Additional testing by: kris (earlier version of the workaround), jhb
X-MFC after: 3 days [1]
Diffstat (limited to 'sys/sparc64/include')
-rw-r--r-- | sys/sparc64/include/cpufunc.h | 17 | ||||
-rw-r--r-- | sys/sparc64/include/pcpu.h | 2 | ||||
-rw-r--r-- | sys/sparc64/include/tick.h | 9 |
3 files changed, 20 insertions, 8 deletions
diff --git a/sys/sparc64/include/cpufunc.h b/sys/sparc64/include/cpufunc.h index 763741d..fc50e20 100644 --- a/sys/sparc64/include/cpufunc.h +++ b/sys/sparc64/include/cpufunc.h @@ -171,6 +171,23 @@ int fasword32(u_long asi, void *addr, uint32_t *val); : : "r" (val), "rI" (xor)); \ } while (0) +/* + * Macro intended to be used instead of wr(asr23, val, xor) for writing to + * the TICK_CMPR register in order to avoid a bug in BlackBird CPUs that + * can cause these writes to fail under certain condidtions which in turn + * causes the hardclock to stop. The workaround is to perform the write + * at the beginning of an I-Cache line directly followed by a dummy read. + */ +#define wrtickcmpr(val, xor) ({ \ + __asm __volatile( \ + " ba,pt %%xcc, 1f ; " \ + " nop ; " \ + " .align 64 ; " \ + "1: wr %0, %1, %%asr23 ; " \ + " rd %%asr23, %%g0 ; " \ + : : "r" (val), "rI" (xor)); \ +}) + static __inline void breakpoint(void) { diff --git a/sys/sparc64/include/pcpu.h b/sys/sparc64/include/pcpu.h index b854921..4e025c1 100644 --- a/sys/sparc64/include/pcpu.h +++ b/sys/sparc64/include/pcpu.h @@ -51,6 +51,8 @@ struct pmap; struct intr_request *pc_irfree; \ struct pmap *pc_pmap; \ vm_offset_t pc_addr; \ + u_long pc_tickref; \ + u_long pc_tickadj; \ u_int pc_mid; \ u_int pc_node; \ u_int pc_tlb_ctx; \ diff --git a/sys/sparc64/include/tick.h b/sys/sparc64/include/tick.h index e317bd8..8586a0d 100644 --- a/sys/sparc64/include/tick.h +++ b/sys/sparc64/include/tick.h @@ -29,15 +29,8 @@ #ifndef _MACHINE_TICK_H_ #define _MACHINE_TICK_H_ -typedef void tick_func_t(struct clockframe *); - void tick_init(u_long clock); -void tick_start(tick_func_t *func); -#ifdef SMP -void tick_start_ap(void); -#endif +void tick_start(void); void tick_stop(void); -tick_func_t tick_hardclock; - #endif |