summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-04-15 22:39:27 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-04-15 22:39:27 +0000
commit0da6aaa8f71ce409bea7f0ede1f94c5e7aae31bf (patch)
treeb264adf54fb2da2a3251ed2659882f7e15be9e30 /sys
parent2176dc4df557ec535a076a6d5d16bf294f08b5df (diff)
Add workaround for UltraSPARC-II errata, where writes to %tick_cmpr would
sometimes fail, which would result in the periodic clock interrupts on a CPU stop. Spotted in a NetBSD commit message, loosely based on code in OpenSolaris.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/include/ctlreg.h4
-rw-r--r--sys/arch/sparc64/sparc64/clock.c4
-rw-r--r--sys/arch/sparc64/sparc64/locore.s15
3 files changed, 18 insertions, 5 deletions
diff --git a/sys/arch/sparc64/include/ctlreg.h b/sys/arch/sparc64/include/ctlreg.h
index 311eae03e47..e94320a8c8c 100644
--- a/sys/arch/sparc64/include/ctlreg.h
+++ b/sys/arch/sparc64/include/ctlreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ctlreg.h,v 1.16 2008/03/08 19:46:59 kettenis Exp $ */
+/* $OpenBSD: ctlreg.h,v 1.17 2008/04/15 22:39:26 kettenis Exp $ */
/* $NetBSD: ctlreg.h,v 1.28 2001/08/06 23:55:34 eeh Exp $ */
/*
@@ -718,7 +718,7 @@ void flush(void *p)
/* read 64-bit %tick register */
#define tick() (sparc_rdpr(tick) & TICK_TICKS)
-extern void next_tick(long);
+extern void tickcmpr_set(u_int64_t);
#endif /* _LOCORE */
#endif /* _SPARC64_CTLREG_ */
diff --git a/sys/arch/sparc64/sparc64/clock.c b/sys/arch/sparc64/sparc64/clock.c
index 135edb0e9ac..a49332cdd02 100644
--- a/sys/arch/sparc64/sparc64/clock.c
+++ b/sys/arch/sparc64/sparc64/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.39 2008/03/29 20:07:36 kettenis Exp $ */
+/* $OpenBSD: clock.c,v 1.40 2008/04/15 22:39:26 kettenis Exp $ */
/* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */
/*
@@ -727,7 +727,7 @@ tickintr(cap)
*/
s = intr_disable();
base = sparc_rdpr(tick);
- sparc_wr(tick_cmpr, (base + tick_increment) & TICK_TICKS, 0);
+ tickcmpr_set((base + tick_increment) & TICK_TICKS);
level0.ih_count.ec_count++;
intr_restore(s);
diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s
index fd2ee1fdca1..014757e2b02 100644
--- a/sys/arch/sparc64/sparc64/locore.s
+++ b/sys/arch/sparc64/sparc64/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.133 2008/04/14 21:04:56 kettenis Exp $ */
+/* $OpenBSD: locore.s,v 1.134 2008/04/15 22:39:26 kettenis Exp $ */
/* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */
/*
@@ -8939,6 +8939,19 @@ _C_LABEL(cpu_clockrate):
.text
/*
+ * On Blackbird (UltraSPARC-II) CPUs, writes to %tick_cmpr may fail.
+ * The workaround is to do a read immediately after the write and make
+ * sure the same cache line.
+ */
+ENTRY(tickcmpr_set)
+ ba,a 1f
+ .align 64
+1: wr %o0, 0, %tick_cmpr
+ rd %tick_cmpr, %g0
+ retl
+ nop
+
+/*
* delay function
*
* void delay(N) -- delay N microseconds