mlel...@serpens.de (Michael van Elst) writes: >In your case, you say it takes ~6 minutes between attachment and >calibration and your hpet runs at 19.2MHz.
>This is enough for HPET_MCOUNT_LO to overflow. This patch adds a separate delay of ~0.1 seconds to calibrate the timers. This should avoid any overflow. Index: sys/dev/ic/hpet.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/hpet.c,v retrieving revision 1.17 diff -p -u -r1.17 hpet.c --- sys/dev/ic/hpet.c 16 May 2020 23:06:40 -0000 1.17 +++ sys/dev/ic/hpet.c 13 Aug 2022 21:24:58 -0000 @@ -54,8 +54,6 @@ static u_int hpet_get_timecount(struct t static bool hpet_resume(device_t, const pmf_qual_t *); static struct hpet_softc *hpet0 __read_mostly; -static uint32_t hpet_attach_val; -static uint64_t hpet_attach_tsc; int hpet_detach(device_t dv, int flags) @@ -147,14 +145,6 @@ hpet_attach_subr(device_t dv) eval = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); val = eval - sval; sc->sc_adj = (int64_t)val * sc->sc_period / 1000; - - /* Store attach-time values for computing TSC frequency later. */ - if (cpu_hascounter() && sc == hpet0) { - (void)cpu_counter(); - val = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); - hpet_attach_tsc = cpu_counter(); - hpet_attach_val = val; - } } static u_int @@ -214,33 +204,37 @@ uint64_t hpet_tsc_freq(void) { struct hpet_softc *sc; - uint64_t td, val, freq; - uint32_t hd; + uint64_t td0, td, val, freq; + uint32_t hd0, hd; int s; if (hpet0 == NULL || !cpu_hascounter()) return 0; - /* Slow down if we got here from attach in under 0.1s. */ sc = hpet0; - hd = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); - hd -= hpet_attach_val; - if (hd < (uint64_t)100000 * 1000000000 / sc->sc_period) - hpet_delay(100000); + + s = splhigh(); + (void)cpu_counter(); + (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); + hd0 = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); + td0 = cpu_counter(); + splx(s); + + hpet_delay(100000); /* * Determine TSC freq by comparing how far the TSC and HPET have - * advanced since attach time. Take the cost of reading HPET - * register into account and round result to the nearest 1000. + * advanced and round result to the nearest 1000. */ s = splhigh(); (void)cpu_counter(); + (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); hd = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_MCOUNT_LO); td = cpu_counter(); splx(s); - hd -= hpet_attach_val; - val = ((uint64_t)hd * sc->sc_period - sc->sc_adj) / 100000000; - freq = (td - hpet_attach_tsc) * 10000000 / val; + + val = (uint64_t)(hd - hd0) * sc->sc_period / 100000000; + freq = (td - td0) * 10000000 / val; return rounddown(freq + 500, 1000); }