mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #69] kernel: i386 8254 system timestamp loses or gains whole ticks when IRQ 0 deliveries merge under CPU hold-off #61
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#61
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/69
Symptom
On i386, the kernel's 8254-based clock (
IOGetTimestamp→clock_get_counter/system_time_stamp,kernel-7/machdep/i386/machine_clock.c~450-490) loses or gains whole ticks when the CPU is held off. Under QEMU TCG on a busy host that happens when the host deschedules the vCPU.Found while fixing #64:
current > last, ~:464-473).pexpert's LAPIC calibration no longer depends on this (fixed in #64), and with the LAPIC clock active the system clock no longer uses it. But systems that stay on the 8254 clock, and every user of
IOGetTimestamp/the system timestamp, still see time stand still or jump under host scheduling delays.Expected
The 8254-based timestamp stays monotonic and doesn't lose time when IRQ 0 deliveries merge or are delayed. Either detect missed reloads (for example by comparing against another free-running reference) and account for them, or derive time from a source that can't lose ticks.
Related: #64, #46, #40 (gettimeofday stepping back).
@raynorpat commented on GitHub (Oct 20, 2026):
Fixed by
a7fbf3287(kernel: count i386 tick reloads with the TSC so ticks merged under interrupt hold-off are not lost), merged into ffs-perf ind0eb6a33b.Mechanism.
system_timer_dispatchadded exactly one tick per interrupt. A CPU held off across two or more reloads gets one merged interrupt, and the other reloads are lost for good. This affects both the 8254 (IRQ 0) and the LAPIC periodic timer.system_time_stamponly noticed a single wrap, and the monotonic clamp then held the stamp still.Fix (
machdep/i386/machine_clock.conly).machine_clock_initagainst 8254 counter 2, using bracketed reads, refusing a sample if counter 2 ran out, with up to 5 tries. CPUID's TSC bit is checked first. With no TSC, or no clean sample, the old code path runs unchanged.Hold-off probe (interrupts off for N ms, timed against counter 2; 6 concurrent boots × 3 runs per row, both clock paths):
Drift, 6 concurrent guests over 300 s with a busy vCPU each:
misc timer,vm clock(no backward steps),make check-miscandcheck-vmpass on both paths.Left open:
hardclock's scheduler and statistics accounting still sees one call per interrupt; only the clock is corrected.