summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64
diff options
context:
space:
mode:
authorScott Soule Cheloha <cheloha@cvs.openbsd.org>2022-12-22 19:51:12 +0000
committerScott Soule Cheloha <cheloha@cvs.openbsd.org>2022-12-22 19:51:12 +0000
commit7cffd29be8ddc926f78306a722ae0466ca092588 (patch)
treeee2bce3fc91bef9527011fc75b2b1c564f157ef4 /sys/arch/sparc64
parent3db97dcf1ff3bcf55b72758630217554bf9b2e55 (diff)
sparc64: move retry logic out of stickcmpr_set()
In some cases, stickcmpr_set() fails to ensure that %STICK_CMPR leads %STICK before returning to the caller. Rewriting the retry logic in C trivially fixes the issue. So move the retry logic out into a new function, stick_rearm(). Issue discovered by miod@, fix tested by miod@. Link: https://marc.info/?l=openbsd-tech&m=167122933414238&w=2 ok kettenis@
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r--sys/arch/sparc64/sparc64/clock.c25
-rw-r--r--sys/arch/sparc64/sparc64/locore.s18
2 files changed, 22 insertions, 21 deletions
diff --git a/sys/arch/sparc64/sparc64/clock.c b/sys/arch/sparc64/sparc64/clock.c
index 92c06d76ec6..56e1cb05a61 100644
--- a/sys/arch/sparc64/sparc64/clock.c
+++ b/sys/arch/sparc64/sparc64/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.72 2022/11/10 07:08:01 jmatthew Exp $ */
+/* $OpenBSD: clock.c,v 1.73 2022/12/22 19:51:11 cheloha Exp $ */
/* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */
/*
@@ -150,6 +150,8 @@ void tick_start(void);
void sys_tick_start(void);
void stick_start(void);
+void stick_rearm(uint64_t);
+
int tickintr(void *);
int sys_tickintr(void *);
int stickintr(void *);
@@ -810,7 +812,7 @@ stickintr(void *cap)
/* Reset the interrupt. */
s = intr_disable();
- stickcmpr_set(ci->ci_tick);
+ stick_rearm(ci->ci_tick);
intr_restore(s);
return (1);
@@ -920,11 +922,26 @@ stick_start(void)
*/
s = intr_disable();
- ci->ci_tick = roundup(stick(), tick_increment);
- stickcmpr_set(ci->ci_tick);
+ ci->ci_tick = stick();
+ stick_rearm(ci->ci_tick);
intr_restore(s);
}
+void
+stick_rearm(uint64_t cmp)
+{
+ uint64_t now, off = 8;
+
+ stickcmpr_set(cmp);
+ now = stick();
+ while (cmp <= now) {
+ cmp += off;
+ stickcmpr_set(cmp);
+ now = stick();
+ off *= 2;
+ }
+}
+
u_int
tick_get_timecount(struct timecounter *tc)
{
diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s
index 3025baf42d1..aa2e2065ade 100644
--- a/sys/arch/sparc64/sparc64/locore.s
+++ b/sys/arch/sparc64/sparc64/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.194 2022/12/08 01:25:45 guenther Exp $ */
+/* $OpenBSD: locore.s,v 1.195 2022/12/22 19:51:11 cheloha Exp $ */
/* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */
/*
@@ -7568,26 +7568,10 @@ END(stick)
ENTRY(stickcmpr_set)
setx STICK_CMP_HIGH, %o1, %o3
- mov 8, %o2 ! Initial step size
-1:
srlx %o0, 32, %o1
stxa %o1, [%o3] ASI_PHYS_NON_CACHED
add %o3, (STICK_CMP_LOW - STICK_CMP_HIGH), %o4
stxa %o0, [%o4] ASI_PHYS_NON_CACHED
-
- add %o3, (STICK_REG_LOW - STICK_CMP_HIGH), %o4
- ldxa [%o4] ASI_PHYS_NON_CACHED, %o1
- add %o3, (STICK_REG_HIGH - STICK_CMP_HIGH), %o4
- ldxa [%o4] ASI_PHYS_NON_CACHED, %o5
- sllx %o5, 32, %o5
- or %o1, %o5, %o1
-
- cmp %o0, %o1 ! Make sure the value we wrote
- bg,pt %xcc, 2f ! was in the future
- add %o0, %o2, %o0 ! If not, add the step size, double
- ba,pt %xcc, 1b ! the step size and try again.
- sllx %o2, 1, %o2
-2:
retl
nop
END(stickcmpr_set)