[PATCH v2 1/2 gnumach] pit, smp: Fix i8254 one shot delay and replace hpet_udelay in smp

Damien Zammit via Bug reports for the GNU Hurd <[email protected]> Tue, 04 Aug 2026 04:08:32 +0000
Newsgroups gmane.os.hurd.bugs
Message-ID <[email protected]>
The one-shot pit delay was not calibrated properly.
This fixes the pit_udelay() function so it can be used for
tiny delays within the kernel.  Removes dependence on HPET for smp.
---
 i386/i386/pit.c | 16 ++++++++++------
 i386/i386/pit.h |  4 ++++
 i386/i386/smp.c |  5 +++--
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/i386/i386/pit.c b/i386/i386/pit.c
index 6c006a98..22a68183 100644
--- a/i386/i386/pit.c
+++ b/i386/i386/pit.c
@@ -66,10 +66,10 @@ int pit0_mode =3D PIT_C0|PIT_SQUAREMODE|PIT_READMODE ;
 unsigned int clknumb =3D CLKNUM;=09=09/* interrupt interval for timer 0 */
=20
 void
-pit_prepare_sleep(int persec)
+pit_prepare_sleep(int usec)
 {
     /* Prepare to sleep for 1/persec seconds */
-    uint32_t val =3D 0;
+    uint64_t val =3D 0;
     uint8_t lsb, msb;
=20
     val =3D inb(PITAUX_PORT);
@@ -77,7 +77,7 @@ pit_prepare_sleep(int persec)
     val |=3D PITAUX_GATE2;
     outb (PITAUX_PORT, val);
     outb (PITCTL_PORT, PIT_C2 | PIT_LOADMODE | PIT_ONESHOTMODE);
-    val =3D CLKNUM / persec;
+    val =3D (uint64_t)CLKNUM * usec / 1000000;
     lsb =3D val & 0xff;
     msb =3D val >> 8;
     outb (PITCTR2_PORT, lsb);
@@ -104,15 +104,19 @@ pit_sleep(void)
 void
 pit_udelay(int usec)
 {
-    pit_prepare_sleep(1000000 / usec);
+    while (usec > MAX_PIT_USEC) {
+        pit_prepare_sleep(MAX_PIT_USEC);
+        pit_sleep();
+        usec -=3D MAX_PIT_USEC;
+    }
+    pit_prepare_sleep(usec);
     pit_sleep();
 }
=20
 void
 pit_mdelay(int msec)
 {
-    pit_prepare_sleep(1000 / msec);
-    pit_sleep();
+    pit_udelay(1000 * msec);
 }
=20
 void
diff --git a/i386/i386/pit.h b/i386/i386/pit.h
index 49e1051b..cc309460 100644
--- a/i386/i386/pit.h
+++ b/i386/i386/pit.h
@@ -87,6 +87,10 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #if=09defined(AT386) || defined(ATX86_64)
 #define CLKNUM=09=091193182
+
+/* PIT counter is 16bit, so max microseconds is:
+ * 0xffffll ticks * 1000000 usec per sec / 1193182 ticks per sec */
+#define MAX_PIT_USEC=0954924
 #endif=09/* AT386 */
=20
 extern void clkstart(void);
diff --git a/i386/i386/smp.c b/i386/i386/smp.c
index dc3a8ba5..6b610020 100644
--- a/i386/i386/smp.c
+++ b/i386/i386/smp.c
@@ -23,6 +23,7 @@
 #include <i386/smp.h>
 #include <i386/cpu.h>
 #include <i386/pio.h>
+#include <i386/pit.h>
 #include <i386/vm_param.h>
 #include <i386at/idt.h>
 #include <i386at/cram.h>
@@ -138,13 +139,13 @@ smp_send_ipi_startup_twice(int bsp_apic_id, int vecto=
r)
          */
         apic_send_ipi(ALL_EXCLUDING_SELF, STARTUP, PHYSICAL, DE_ASSERT, ED=
GE, vector, bsp_apic_id);
=20
-        hpet_udelay(10);
+        pit_udelay(10);
=20
         /* Wait for other cpu to accept IPI */
         wait_for_ipi();
         send_err =3D lapic->error_status.r;
=20
-        hpet_udelay(10);
+        pit_udelay(10);
=20
         lapic->error_status.r =3D 0;
         accept_err =3D lapic->error_status.r & 0xef;
--=20
2.51.0