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 }