:: commit 8e842edecfe0ca74ad29b7a16a428769e4a15b25

Mintsuki <mintsuki@protonmail.com> — 2026-04-05 09:08

parents: e7b5bbbdff

sys/cpu: Add PIT-based TSC calibration for BIOS

diff --git a/common/protos/limine.c b/common/protos/limine.c
index b8767436..6a782cf4 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -1595,7 +1595,6 @@ FEAT_END
 #endif
 
     // Bootloader Performance
-    // rdtsc_usec depends on EFI boot services
 FEAT_START
     if (usec_at_bootloader_entry == 0) {
         break;
diff --git a/common/sys/cpu.h b/common/sys/cpu.h
index 60cc72bd..2b006280 100644
--- a/common/sys/cpu.h
+++ b/common/sys/cpu.h
@@ -504,15 +504,6 @@ static inline uint64_t rdtsc_usec(void) {
 }
 
 static inline void stall(uint64_t us) {
-#if defined(BIOS)
-    if (tsc_freq == 0) {
-        // ~1 us per inb on ISA/LPC bus
-        for (uint64_t i = 0; i < us; i++) {
-            inb(0x80);
-        }
-        return;
-    }
-#endif
     uint64_t ticks = (tsc_freq * us + 999999) / 1000000;
     uint64_t next_stop = rdtsc() + ticks;
     while (rdtsc() < next_stop);
diff --git a/common/sys/cpu.s2.c b/common/sys/cpu.s2.c
index d4d6ec89..a5ea5bff 100644
--- a/common/sys/cpu.s2.c
+++ b/common/sys/cpu.s2.c
@@ -22,5 +22,28 @@ void calibrate_tsc(void) {
     if (tsc_end > tsc_start) {
         tsc_freq = (tsc_end - tsc_start) * 1000ULL;
     }
+#elif defined(BIOS)
+    // Calibrate TSC using PIT channel 2
+    // PIT oscillator frequency: 1193182 Hz
+    // Count of 11932 gives ~10ms calibration interval
+    #define PIT_CALIBRATION_COUNT 11932
+
+    uint8_t port61 = inb(0x61);
+    outb(0x61, port61 & ~0x03); // disable gate and speaker
+    outb(0x43, 0xb0); // channel 2, lobyte/hibyte, mode 0, binary
+    outb(0x42, PIT_CALIBRATION_COUNT & 0xff);
+    outb(0x42, (PIT_CALIBRATION_COUNT >> 8) & 0xff);
+
+    outb(0x61, (inb(0x61) | 0x01)); // enable gate to start counting
+    uint64_t tsc_start = rdtsc();
+
+    while ((inb(0x61) & 0x20) == 0); // wait for output high
+    uint64_t tsc_end = rdtsc();
+
+    outb(0x61, port61); // restore
+
+    if (tsc_end > tsc_start) {
+        tsc_freq = (tsc_end - tsc_start) * 1193182 / PIT_CALIBRATION_COUNT;
+    }
 #endif
 }
tab: 248 wrap: offon