Skip to content

v0.2.5

Choose a tag to compare

@github-actions github-actions released this 15 Sep 01:46
· 12 commits to main since this release

On Windows with an AMD CPU, the guest's clock ran about 11% slow, and in coarse steps. Nothing failed, so nothing reported it. Servers in the guest ran slow and in bursts instead: in Ragnarok Offline, monsters and players appeared to teleport on machines with plenty of power (ragnarokoffline.app#144). This release fixes the clock and writes the guest's clock health to nebulad.log. Intel machines, macOS and Linux were not affected.

The guest could not measure its own TSC on AMD

Linux reads the TSC frequency from CPUID leaf 0x15, which nebula's WHP backend provides. But Linux only trusts that leaf on Intel. Everywhere else it times the TSC by polling PIT channel 2, and needs at least 1000 reads in 10 ms. Under WHP every read exits to userspace, so the calibration fails:

tsc: Unable to calibrate against PIT
tsc: No reference (HPET/PMTIMER) available
tsc: Marking TSC unstable due to could not calculate TSC khz
clocksource: Switched to clocksource refined-jiffies
Unstable clock detected, switching default tracing clock to "global"

refined-jiffies only moves forward when a timer interrupt arrives, and on AMD those came from an emulated PIT that drifted.

On AMD hosts, and on any host where Linux won't read leaf 0x15, the krun worker now measures the host TSC against QueryPerformanceCounter. It boots the guest with tsc_early_khz=<khz> tsc=reliable. WHP runs the guest on the host's TSC, so the host's measurement is the guest's frequency.

The emulated PIT's channel 0 also fires on fixed deadlines now. Previously it slept for one period after each tick, so every oversleep added to the drift.

Measured on Windows 10 19045 with the AMD code path forced (guest max basic CPUID leaf clamped to 0x10), guest /proc/uptime against the host over 60 s:

clocksource guest time / host time
v0.2.4 refined-jiffies 0.889
v0.2.4 + deadline PIT only refined-jiffies 0.997
v0.2.5 tsc 1.0000
v0.2.5, Intel path (unchanged) tsc 1.0001

The guest clock in nebulad.log

About 30 s after boot, nebulad logs the guest's clocksource, its timer devices and the kernel's calibration messages, as guest timers: lines. After 90 s, and then every 5 minutes, it logs:

INFO nebulad::clock: guest clock: 1.0001x host over 61s, sleep(1s) took 1000ms, timer irqs/s pit=0 local=127

The line is a WARN when the guest clock is more than 1% off, when a one-second sleep takes over 1.1 s, or when the PIT is still driving the guest's timers. Set NEBULA_NO_CLOCK_REPORT to turn it off.

Embedders: new guest images come with this release, so install-image applies after upgrading. The clock fix itself is on the host side, in nebulad and the krun worker.