Page MenuHomeFreeBSD

x86: hyperv: use Hyper-V time counter (rather than i8254) to calibrate TSC
AbandonedPublic

Authored by decui_microsoft.com on Feb 3 2016, 6:30 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, Jun 23, 12:49 AM
Unknown Object (File)
Sun, Jun 23, 12:47 AM
Unknown Object (File)
Sat, Jun 22, 8:33 PM
Unknown Object (File)
May 23 2024, 12:01 PM
Unknown Object (File)
May 10 2024, 5:38 AM
Unknown Object (File)
Apr 23 2024, 5:28 AM
Unknown Object (File)
Apr 23 2024, 5:27 AM
Unknown Object (File)
Apr 19 2024, 2:33 PM
Subscribers

Details

Summary

The i8254 PIT counter emulated by Hyper-V is not reliable.

In probe_tsc_freq() -> DELAY -> init_ops.early_delay() -> i8254_delay(),
getit() can return these values when it is invoked 10 times:

1 pit count0 = 228
2 pit count0 = 131
3 pit count0 = 34
4 pit count0 = 65473 <-- this is a normal wrap-around.
5 pit count0 = 65375
6 pit count0 = 65278
7 pit count0 = 65180
8 pit count0 = 65388 <-- this is bad!
9 pit count0 = 65290

10 pit count0 = 65193

For the 8th time, the 'delta' in i8254_delay() is < 0 while
it shouldn't, so the later "delta += i8254_max_count;" and
"ticks_left -= delta" will cause i8254_delay() to wait shorter than
expected, and finally probe_tsc_freq() get a smaller 'tsc_freq', e.g.,
a 2.5GHz CPU can be detected as 1.3GHz.

A smaller 'tsc_freq' can cause time inaccuracy in dtrace.
It can also cause warnings like

calcru: runtime went backwards from 50 usec to 25 usec for pid 0 (kernel)
calcru: runtime went backwards from 1471 usec to 743 usec for pid 0 (kernel)
calcru: runtime went backwards from 40 usec to 20 usec for pid 0 (kernel)
calcru: runtime went backwards from 18 usec to 9 usec for pid 0 (kernel)
calcru: runtime went backwards from 46204978 usec to 23362331 usec for pid 0 (kernel)

We should use Hyper-V time counter, which is much more reliable than i8254,
to calibrate TSC.

And, we must use Hyper-V timer counter for Hyper-V Generation-2 (UEFI) VM,
because i8254 doesn't exist for such a VM.

Please suggest how I should improve the patch, e.g., should I move
the new hyperv_delay() to a new file?

Submitted by: Dexuan Cui <decui@microsoft.com>

Test Plan

Boot the kernel with boot_verbose="YES", and check dmesg:

dmesg | grep "TSC clock"

Calibrating TSC clock ... TSC clock: 2500003082 Hz

(Without the patch, the TSC Hz is only ~1.3GHz in my test)

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 2368
Build 2384: arc lint + arc unit

Event Timeline

decui_microsoft.com retitled this revision from to x86: hyperv: use Hyper-V time counter (rather than i8254) to calibrate TSC.
decui_microsoft.com updated this object.
decui_microsoft.com edited the test plan for this revision. (Show Details)
This revision is now accepted and ready to land.Feb 4 2016, 1:07 AM
adrian edited edge metadata.

hah, good catch!