Skip to content

[vmm][whp] Override CPUID leaf 0x16 with WHP clock frequency#11

Draft
esaurez wants to merge 2 commits into
devfrom
enhancement-vmm-cpuid-frequency-override
Draft

[vmm][whp] Override CPUID leaf 0x16 with WHP clock frequency#11
esaurez wants to merge 2 commits into
devfrom
enhancement-vmm-cpuid-frequency-override

Conversation

@esaurez

@esaurez esaurez commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Replica of nanvix#1919.

Problem

Hyper-V zeros out CPUID leaf 0x16 (Processor Frequency Information) even on CPUs that support it. The guest kernel checks this leaf for TSC base frequency to enable RDTSC-based LAPIC timer calibration. When leaf 0x16 returns 0, it falls back to the PIT busy-wait loop, generating ~908 unnecessary VM exits.

Fix

The VMM now queries the host TSC frequency via WHvGetCapability(ProcessorClockFrequency), converts Hz to MHz, and injects it into CPUID leaf 0x16 EAX via WHvPartitionPropertyCodeCpuidResultList.

Benchmark Results (p50, 50 iterations)

Metric Dev baseline LAPIC + this fix Improvement
total 81,106 us 67,029 us -17.4%
guest_exec 59,384 us 48,641 us -18.1%

Depends on: enhancement-kernel-lapic-calibration-whp (guest-side RDTSC calibration)

ppenna and others added 2 commits April 7, 2026 08:38
- Reduce PIT-based calibration window from 10 ms to 1 ms.
- Replace PIT-based calibration with RDTSC spin loop when CPUID
  leaf 0x16 is available, eliminating ~100 VM exits during boot.
- Fall back to PIT-based calibration (1 ms window) when leaf 0x16
  is unavailable instead of guessing TSC frequency.
- Add max-iteration guard to RDTSC spin loop to prevent hangs.
- Fix CPUID helper to check max supported leaf and set ECX=0
  explicitly for well-defined subleaf selection.
Hyper-V zeros out CPUID leaf 0x16 (Processor Frequency Information)
even on CPUs that support it (e.g. Skylake-SP). This prevents the
guest kernel from using RDTSC-based LAPIC timer calibration, forcing
a fallback to the PIT busy-wait loop which generates ~908 VM exits.

Query the host TSC frequency via WHvGetCapability(ProcessorClockFrequency)
and inject it into CPUID leaf 0x16 EAX via WHvPartitionPropertyCodeCpuidResultList
before partition setup. The guest kernel (on the LAPIC calibration branch)
sees a non-zero base frequency and uses an RDTSC spin loop instead of PIT,
eliminating ~908 PMIO read exits.

Benchmark results (p50, 50 iterations):
  Before (dev):       81,106 us total, 59,384 us guest_exec
  After  (this fix):  67,029 us total, 48,641 us guest_exec
  Improvement:        17.4% total, 18.1% guest_exec

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants