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);
 }
 


Reply via email to