sparc64: move retry logic out of stickcmpr_set()
authorcheloha <cheloha@openbsd.org>
Thu, 22 Dec 2022 19:51:11 +0000 (19:51 +0000)
committercheloha <cheloha@openbsd.org>
Thu, 22 Dec 2022 19:51:11 +0000 (19:51 +0000)
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@

sys/arch/sparc64/sparc64/clock.c
sys/arch/sparc64/sparc64/locore.s

index 92c06d7..56e1cb0 100644 (file)
@@ -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)
 {
index 3025baf..aa2e206 100644 (file)
@@ -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)