From 7cffd29be8ddc926f78306a722ae0466ca092588 Mon Sep 17 00:00:00 2001 From: Scott Soule Cheloha Date: Thu, 22 Dec 2022 19:51:12 +0000 Subject: 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@ --- sys/arch/sparc64/sparc64/clock.c | 25 +++++++++++++++++++++---- sys/arch/sparc64/sparc64/locore.s | 18 +----------------- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'sys/arch/sparc64') 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) -- cgit v1.2.3