Repository navigation
time ABI: publish the host's clock correction with each time sample - #1061
Draft
Pedro Henrique Penna (ppenna) wants to merge 5 commits into
Draft
Pedro Henrique Penna (ppenna) wants to merge 5 commits into
Pedro Henrique Penna (ppenna) wants to merge 5 commits into
Conversation
Pin microsoft/openvmm#4830 at 858b2f93aa78d35df6fdd217322a7f4cfb57b080, six commits on 3d7512af653717aa9123595e993a56cb8587106a, the previous pin and the head of feature/microvm/dev. They are the commits of microsoft/openvmm#4809, rebased there unchanged. Under time ABI 1 the guest paired host UTC with its own clock: nvx-time read CLOCK_REALTIME around the port write that latches a time sample and accepted the pairing only within 1 ms at boot and restore, or 50 us for its discipline, so a port write that a loaded host served late cost a sample, and three cost a boot or a restore. It then estimated how fast host UTC runs against its TSC by steering the kernel's PLL over minutes, although the host's time service already knows that rate. Time ABI 2 has OpenVMM pair each sample's host UTC with the guest TSC on the host and publish with it the host's clock correction, which the host OS reports (adjtimex on Linux, GetSystemTimeAdjustmentPrecise on Windows), the bound of the correction's error, the status and maximum error of host UTC, and a disruption counter, which changes on a host suspension, a step of host UTC, or a change of the guest TSC's offset. The version-2 sample is 48 bytes. CPUID leaf 0x40000002 reports time ABI 2.0 (EBX 0x00020000). Restore packet 5 drops host UTC, so its header shrinks to 24 bytes, and the guest's repair takes a time sample instead. The guest moves with the pin, since a guest of one time ABI fails the other's conformance check: - nvx::contract: TIME_ABI_VERSION 2 and RESTORE_PACKET_VERSION 5. - Pairing: the guest reads its TSC before and after the selector write, and CLOCK_REALTIME between those reads, and accepts a sample only if its TSC lies within that bracket, widened by the published pairing bound and 1 us of skew. It compares host UTC with CLOCK_REALTIME at the sample's TSC, moving its CLOCK_REALTIME read there at the rate at which Linux counts it; the offset's uncertainty is the pairing bound, half the bracket, and 2,000 ppm of that move. - Rate: from the host's correction and the TSC rate, which the guest reads once from the Hyper-V TSC frequency MSR (0x40000022) and keeps in its time state, the guest computes the adjtimex frequency that makes CLOCK_REALTIME, which Linux counts at its kHz rounding of the TSC rate, run at host UTC's rate. It clamps that frequency to Linux's 500 ppm limit and reports whether it did. - Discipline: boot steps the clock to host UTC and holds that frequency with STA_FREQHOLD, so that the kernel's PLL corrects only the phase. Every poll holds the latest correction and slews the measured offset, or steps it from 128 ms on. A changed disruption counter returns the daemon to its fast cadence. Boot, restore, and polls take up to three samples within 100 us; a boot that gets none fails its check, and a restore fails its repair. The maximum and estimated errors that the guest sets include host UTC's maximum error only when the host reports a synchronized clock; the guest never marks its clock unsynchronized on the host's behalf. - Restore: the repair reads packet 5 and takes its time sample in the same port transaction, then steps the clock and holds the frequency. - State: the time state records the host's status, correction, and correction bound, host UTC's maximum error, the disruption counter, and whether the frequency was limited. nvx-time sample prints a sample's fields and the guest's pairing, and the test hooks packet, sample, pair, frequency, and correction take the new fields. Templates record time ABI version 2, so the manifest reader refuses a template of time ABI 1, which must be recaptured. The fixtures' manifests, which OpenVMM's generator regenerated at the pin, differ from the previous ones only in that version. The template-key vectors keep the contract versions that their test fixes. Comments, the nvx-rs README, and nvx-snapshot name the new versions. OpenVMM's protocol vectors and CPU profiles are unchanged at the pin. Part of #1009 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The architecture guide described time ABI 1: a 16-byte time sample that the guest pairs with its own clock within 1 ms, or 50 us for its discipline, a guest that estimates host UTC's rate itself, and restore packet 4, which carries host UTC latched at its first selection. Describe time ABI 2, which the previous commit pins. 3.2, Clock and time: - Table 3.5: CPUID leaf 0x40000002 reports time ABI 2.0 in EBX. - 3.2.4: the host clock correction of every time sample includes a restore's rate deviation, so that the guest compensates it from its repair on. - 3.2.6, Backend obligations: every backend knows the guest TSC's offset from the host TSC before any processor runs, at cold boot and at every restore, so that the VMM pairs each sample's host UTC with the guest TSC. - 3.2.9, Time samples, rewritten: Figure 3.1 lays out the 48-byte version-2 sample field by field; the text gives the guest's pairing, the bracket check and the uncertainty of the offset, how it computes the adjtimex frequency that makes CLOCK_REALTIME run at host UTC's rate from the correction and the TSC rate, and the 500 ppm limit that it reports. Table 3.10 bounds every use, boot, restore, and the discipline, at 100 us and three attempts. The samples are no paravirtual clock: they feed only the wall-clock discipline, and the TSC stays the guest's clocksource. - 3.2.10, Guest obligations: the time state's new fields, a boot that takes a sample within the bound before readiness, steps to host UTC, and holds the frequency that the host's correction gives, and a discipline that holds that frequency at every accepted sample, so that the kernel's PLL only slews the phase, and returns to its fast cadence when the disruption counter changes. 5.5, Restore protocol: Figure 5.7 lays out restore packet 5, whose header is 24 bytes and carries no UTC, 88 bytes without memory ranges, and flag 3 also covers the host clock rate's test hook. The guest's repair steps take a time sample in the packet's port transaction and set the clock and its rate from it. 3.1, Platform control device, says that time samples pair host UTC with the guest TSC and carry the host's correction, and that the guest checks the pairing against TSC reads around the port write. 1.2, Non-goals, names kvmclock, Hyper-V's reference TSC page, and VMClock among the excluded paravirtual clocks, and says what the time samples feed instead. The build guide's description of nvx-time names restore packet 5 and the version-2 sample parsers and the correction that the discipline applies. Part of #1009 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Since this branch split from dev, H4's rate qualification gained the 250 ppm budget that time ABI 2 leaves for the host's clock correction, a retry when chronyd's skew straddles that limit, a warning above the old 100 ppm bound, the kernel PLL's estimate when chronyd is absent, and the average correction since boot as evidence (#1008). Keep all of those checks and their evidence. Time ABI 2 also changes what H4 must learn directly from the host. Every time sample publishes the host's clock correction, which the guest holds, so a qualified host must have a time service maintaining that correction. H4 now additionally: - Fails unless the host publishes a synchronized correction, read as OpenVMM reads it: on Linux, adjtimex reports neither STA_UNSYNC nor STA_CLOCKERR; on Windows, GetSystemTimeAdjustmentPrecise reports an applied adjustment. - Reports the status, correction, and host UTC's maximum error in its detail and as host_clock_status and host_correction_ppm summary facts. The direct correction is evidence; the independent 250 ppm rate gate continues to protect the guest's correction budget. - Keeps the chronyd estimate and its skew, conclusive re-reads, the kernel PLL fallback, the warning, and the average since boot, instead of replacing them with the instantaneous correction. The Linux reader shares the typed struct timex reader with the PLL and H7. The Windows reader uses the precise API's direction: the performance counter ticks increment times per second, and host UTC counts a second for every adjustment ticks, so a larger adjustment slows UTC. The H4 tests cover synchronized, free-running, unreliable, and unknown host clocks; Linux frequency, tick, and maximum-error mapping; Windows' failed, zero, disabled, and synchronized adjustment states and correction direction; the summary facts; and the interaction with the rate budget, warnings, chronyd re-reads, PLL fallback, and boot average. The CI guide, validate-runner, and its test describe the combined gate. Part of #1009 Refs #1008 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Time ABI 2 publishes the host's clock correction with every sample, and the guest holds it as its frequency correction. Add the `time-host-correction` microVM scenario to check that behavior when host UTC runs at a deliberately different rate from the guest TSC. An unhooked cold boot first reads the host's own correction. OpenVMM's `host-rate-offset-ppm` hook then drives: - a hooked cold boot whose published correction stays below Linux's 500 ppm frequency limit; - a restore at another correction below the limit; and - a restore in the host correction's direction that exceeds the limit, where the guest must hold +/-500 ppm and report frequency_limited=1. The ordinary hooks solve OpenVMM's multiplicative composition of the host and hook rates for targets of 200 and 150 ppm against the host correction's sign. They are clamped to OpenVMM's accepted +/-10,000 ppm hook range; at its edge they use the closest composed correction whose effective Linux correction, after the declared TSC rate's kHz rounding, stays below the limit. A host correction that no accepted hook can keep below it fails before OpenVMM starts with a diagnostic naming both bounds. The limit hook is 900 ppm in the host correction's direction. Each phase requires the test-hook flag and checks that the boot step or restore repair did not retain a stale correction. Up to three pairs of samples pair host UTC and the guest's realtime clock with the guest TSC. Before each pair the guest cancels an earlier poll's kernel phase slew while keeping the frequency held, and brackets the samples with the live discipline state. A changed disruption counter, held correction, or clock-step state discards that window. The checker verifies the first stable pair with its fresh state, within its pairing uncertainty and the allowance for host slews. The limit phase requires the saturated frequency and flag explicitly. Linux counts the declared TSC rate rounded down to the kHz. The checker derives the permitted difference between the host and kernel frequency corrections from each report's tsc_hz and the worst 999 Hz loss, instead of assuming a rate of at least 1 GHz. The regression at 500,000,999 Hz accepts the valid 1,998 ppb difference. Another regression rejects a -10,396 ppm host at that rate: although the largest hook publishes -499.96 ppm, Linux must hold -501.957 ppm. Conversely, a +10,607 ppm host and -10,000 ppm hook publish +500.930 ppm but need only +498.931 ppm from Linux, which both the solver and checker accept. The hook tests cover both +/-10,000 ppm boundaries and reject corrections that cannot be offset. The shard plan runs the scenario on KVM, MSHV, and WHP. Unit tests cover the successful phases, stale and ignored corrections, the clock-rate checks, host slews, disruption and discipline-update retries, saturation, missing or unhooked samples, the full 500 MHz ABI range, OpenVMM's hook range, and the probe, boot, and restore command sequence. Part of #1009 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Record the six commits that the first commit of this series pins as positions 373-378 of the microVM chain, and move the NVX pin to 858b2f93a. Positions 373-378 move NVX's time ABI to version 2: the shared host TSC bracket, the host OS's discipline of host UTC, the publication of host UTC paired with the guest TSC and its correction, the guest TSC's offset on every backend, the version-2 time sample and restore packet 5, and the Guide's description. They change the time-ABI backends, portb device, restore packet, and VM worker that positions 159-269 added, and replayed onto upstream main they conflict in every file that they change except the two that they add. Position 377 also adapts petri's microVM configuration from PR15 and the ttrpc microVM test from PR25. The six commits are microsoft/openvmm#4809's, which microsoft/openvmm#4830 rebases unchanged onto 3d7512af6, position 372 and the current head of feature/microvm/dev since microsoft/openvmm#4816 merged positions 371 and 372. Since they follow that port rather than the unassigned positions 346-370, they start a new unassigned range. Update the scope, physical DAG, after-tip count and table, and remarks. The pin is 221 commits past the mapped tip. Part of #1009 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
H4’s early failure return discards computed budget warnings, removing diagnostics from CI annotations and the summary when another check also fails.
1 open issue
What changed in this PR
Updates NVX’s guest-time integration to time ABI 2, addressing #1009 by applying OpenVMM’s published host clock correction instead of estimating it in each guest.
Changes:
- Applies published corrections at boot, during polling, and after restore, with Linux’s frequency limit and expanded time-state reporting.
- Adds time-ABI and restore-packet compatibility checks and requires synchronized host clock corrections in H4.
- Adds the
time-host-correctionmicroVM scenario, supporting tests, shard assignments, and architecture documentation.
| File | Description |
|---|---|
SOURCE-MANIFEST.json |
Declares time ABI 2 and restore packet 5. |
scripts/test_time_abi.py |
Tests host correction mapping and H4 qualification. |
scripts/test_nvx_tools.py |
Updates release-manifest fixtures and assertions. |
scripts/test_microvm_tests.py |
Tests the new correction scenario and report validation. |
scripts/nvx_tools/time_abi.py |
Updates ABI documentation and diagnostics to version 2. |
scripts/nvx_tools/microvm_tests.py |
Implements the host-correction scenario and rate checks. |
scripts/nvx_tools/microvm_test_scripts/time-host-correction.sh.in |
Collects guest state and bounded measurement windows. |
scripts/nvx_tools/microvm_test_scripts/snapshot-core.sh |
Removes the obsolete packet version from a comment. |
scripts/nvx_tools/microvm_shards.json |
Adds the scenario and rebalances backend shards. |
scripts/nvx_tools/doctor.py |
Reads host clock corrections and gates synchronization status. |
nvx-rs/tests/guest_tools.rs |
Updates packet, sample, and command-output tests. |
nvx-rs/tests/fixtures/template/README.md |
Documents time ABI 2 fixture provenance and regeneration. |
nvx-rs/src/host/template/test_support.rs |
Uses the current time ABI constant in fixtures. |
nvx-rs/src/host/template/manifest/tests.rs |
Tests rejection of incompatible time ABI versions. |
nvx-rs/src/host/launch.rs |
Removes version-specific wording from a comment. |
nvx-rs/src/host/cli/download/install/tests.rs |
Adds time and restore versions to manifest fixtures. |
nvx-rs/src/host/artifacts/tests.rs |
Updates artifact compatibility fixtures. |
nvx-rs/src/host/artifacts/mod.rs |
Broadens contract-incompatibility error wording. |
nvx-rs/src/guest/time/test_mode.rs |
Updates decoder hooks and adds PLL phase clearing. |
nvx-rs/src/guest/time/state.rs |
Records host corrections, bounds, status, and disruptions. |
nvx-rs/src/guest/time/mod.rs |
Updates module documentation to time ABI 2. |
nvx-rs/src/guest/time/daemon.rs |
Holds published frequency corrections and handles disruptions. |
nvx-rs/src/guest/time/cpu_mask.rs |
Removes version-specific wording from documentation. |
nvx-rs/src/guest/time/commands.rs |
Reports expanded samples and derived frequency corrections. |
nvx-rs/src/guest/time/checks.rs |
Expects time ABI 2 in the CPUID identity. |
nvx-rs/src/guest/time/api.rs |
Applies sampled corrections during boot and restore repair. |
nvx-rs/src/guest/sys/mod.rs |
Re-exports the frequency-hold type. |
nvx-rs/src/guest/sys/discipline.rs |
Adds frequency holding, error estimates, and phase clearing. |
nvx-rs/src/contract.rs |
Advances versions and validates all bundled contracts. |
nvx-rs/README.md |
Documents ABI 2 and expanded artifact requirements. |
nvx-rs/build.rs |
Updates bundled-artifact incompatibility error wording. |
guest/common/nvx-snapshot |
Updates comments for packet 5 and sampled clock repair. |
doc/usage.md |
Describes the host-correction scenario. |
doc/openvmm-upstream-roadmap.md |
Maps the new pin and six time-ABI commits. |
doc/distribution.md |
Documents expanded bundled-contract publication checks. |
doc/design/5.5-restore-protocol.md |
Specifies packet 5 and sample-based clock repair. |
doc/design/3.2-clock-and-time.md |
Specifies version-2 samples and held frequency corrections. |
doc/design/3.1-platform-control-device.md |
Documents host-paired samples and their corrections. |
doc/design/1.2-non-goals.md |
Clarifies the distinction from paravirtual clocks. |
doc/ci.md |
Documents the scenario and updated host qualification. |
doc/build.md |
Describes the guest’s ABI 2 time handling. |
.github/actions/validate-runner/action.yml |
Updates comments describing host clock qualification. |
Review effort: Max
Comment on lines
+1295
to
+1296
| if problems: | ||
| return CheckResult("H4", False, "; ".join(problems) + f"; {detail}") |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #1009. Replaces #1018, rebuilt on
devat682a5ca4d: pins microsoft/openvmm#4830 at858b2f93aa78d35df6fdd217322a7f4cfb57b080, microsoft/openvmm#4809's six commits rebased unchanged onto the current head offeature/microvm/dev, which moves every microVM to time ABI 2: OpenVMM pairs each time sample's host UTC with the guest TSC on the host and publishes with it the host's clock correction, which the guest now applies instead of estimating it over minutes. The guest,nvx.py doctor's H4, the architecture guide, and a new microVM scenario move with the pin. #1018 and microsoft/openvmm#4809 stay open and unchanged.Based on
devat682a5ca4d, whose pin,3d7512af6(#1036), is the head offeature/microvm/devsince microsoft/openvmm#4816 merged. microsoft/openvmm#4830 is six commits directly on it, and the pin is that pull request's head commit itself.Landing order. microsoft/openvmm#4830 lands first, by fast-forwarding
feature/microvm/devto858b2f93aonce its CI passes (microsoft/openvmmallows only squash merges, which would land a different commit). Then mark this pull request ready, which starts NVX's CI at its exact head, and merge it; #1018 and microsoft/openvmm#4809 can then close.Change
bf3f14217openvmmopenvmm,nvx-rs/,guest/common/nvx-snapshot, wording inscripts/3d7512af6->858b2f93a, and the guest of time ABI 2 and restore packet 5, which must move with it: the version-2 sample's decoder, the pairing against the guest's own TSC bracket, the frequency correction from the host's correction, the discipline that holds it, the restore repair's sample, the time state's new fields,nvx-time sample, and the template fixtures' manifests02d4f932cdocdoc/design/{1.2,3.1,3.2,5.5},doc/build.md7f19c779ddoctorscripts/nvx_tools/doctor.py,scripts/test_time_abi.py,doc/ci.md,validate-runner6d4a96b86test-microvmscripts/nvx_tools/microvm_tests.py, its guest script and tests,nvx-rs/src/guest/{sys/discipline.rs,time/test_mode.rs},microvm_shards.json,doc/ci.md,doc/usage.mdtime-host-correctionscenario, its cross-guest PLL phase-clear hook, and the wait for Linux's cached tick length468505ed8docdoc/openvmm-upstream-roadmap.mdAt the pin, OpenVMM's control-session protocol vectors, the source excerpts and contract versions that
nvx-rscopies, and its built-in CPU profiles matchnvx-rs's copies (openvmm_vectors: 3 tests,openvmm_cpu_profiles: 1 test, all passing), and OpenVMM's generator writes the template fixtures' manifests byte for byte.Time ABI 2
OpenVMM (microsoft/openvmm#4830). Writing
0xa7to the portb status port latches a 48-byte version-2 sample: host UTC and the guest TSC at the same instant, paired on the host through the guest TSC's offset, which every backend measures before any VP runs (KVM'sKVM_VCPU_TSC_OFFSET; VP 0's TSC between two host TSC reads on MSHV and WHP), with the pairing's bound; the status of host UTC; a disruption counter, which changes on a host suspension, a step of host UTC, or a change of the offset; and the host's correction, how fast host UTC runs against the guest TSC counted at the declared rate, with the bounds of its error and of host UTC's. OpenVMM reads the correction from the host OS, whatever time service runs there:adjtimexon Linux, and on WindowsGetSystemTimeAdjustmentPrecise, whose increment is the performance counter's frequency and whose adjustment is the counter's ticks in each second of UTC, so that UTC runs at the increment over the adjustment of the counter's rate. After a restore the correction includes the restore's rate deviation. Restore packet 5 drops host UTC; CPUID leaf0x40000002reports time ABI 2.0, and snapshots record time ABI version 2.Guest (
nvx-rs).nvx-timereads its TSC around the selector write and its realtime clock between two more TSC reads, accepts a sample only if its TSC lies in that bracket, widened by the pairing bound and the 1 µs skew bound, and takes the offset from host UTC at the sample's TSC. It sets the kernel's frequency correction so that its realtime clock, which Linux counts at the TSC rate rounded down to the kHz, runs at host UTC's published rate, within Linux's ±500 ppm, and reportsfrequency_limitedbeyond it. Boot steps to host UTC and holds that frequency withSTA_FREQHOLD, so that the kernel's PLL corrects only the phase; every poll holds the latest correction, and a changed disruption counter returns the discipline to its fast cadence. Boot, restore, and polls take up to three samples within 100 µs, where time ABI 1 accepted 1 ms at boot and restore. A restore's repair takes its sample in the packet's port transaction, so a clone runs at the destination host's correction from its repair on. The time state reports the host's status, correction and its bound, host UTC's maximum error, and the disruption counter.The issue's next steps
dev's 250 ppm guest-budget gate, chronyd re-reads, warning, kernel-PLL fallback, and average-since-boot evidence, and additionally requires the host to publish a synchronized correction. The directly read status, correction, and maximum error are evidence; the independent rate gate still protects the guest's correction budget.time-host-correctionreads the host's own correction from an unhooked cold boot. OpenVMM'shost-rate-offset-ppmhook then selects ordinary corrections below Linux's limit and a 900 ppm limit phase. The ordinary hooks solve OpenVMM's multiplicative rate composition and stay within its +/-10,000 ppm parser range and fail explicitly if no accepted hook can avoid saturation; hook selection validates Linux's effective correction after TSC-rate rounding down to the ABI's 500 MHz minimum, and each sample window records the initial, before, and after discipline states, clears an earlier PLL phase offset throughnvx-time, and gets three bounded attempts after host UTC, the accepted-sample count, or the discipline changes. Alpine and Ubuntu both run it on KVM and MSHV; CI runs the Alpine suite on WHP.The open questions:
0xa7sample, 48 bytes, rather than a page that the guest maps.E_MANIFEST_TIME); snapshots and templates must be recaptured.Compatibility
nvx-rsmove together with the pin.Validate runnerstep reports its runner's.Rebuild and equivalence
feature/microvm/devmoved from5e0ab772eto3d7512af6when [DO NOT REVIEW] microVM: reject explicit host-loopback access on a /30 IPv4 network openvmm#4823 (explicit host-loopback access refused on a /30 network) and [DO NOT REVIEW] vmm_tests: run the KVP IC test on Windows Server 2025 (port of #4803) openvmm#4816 (the KVP IC VMM test on Windows Server 2025) merged. [DO NOT REVIEW] microVM: publish the host's clock correction with each time sample openvmm#4830 rebases [DO NOT REVIEW] microVM: publish the host's clock correction with each time sample openvmm#4809's six commits there:git range-diffmarks all six identical (=), and the rebased tree,5d3b9c03e, is exactly the conflict-free three-way merge of37ff2f9a5with3d7512af6over5e0ab772e. The three new base commits share only the CLI reference with them, in another section, and touch none of the time ABI's code. Every commit has a good SSH signature.git range-diff f9de4630c..f8b6fbf3f 682a5ca4d..6d4a96b86keeps commits 2-4 of time ABI: publish the host's clock correction with each time sample #1018 identical, and commit 1 differs only in the gitlink,3d7512af6 -> 858b2f93awhere time ABI: publish the host's clock correction with each time sample #1018 has5e0ab772e -> 37ff2f9a5, and in the pin that its message names.dev's changes since time ABI: publish the host's clock correction with each time sample #1018's base merged without conflicts indoc/ci.md,doc/usage.md,nvx-rs/README.md, andscripts/{nvx_tools/microvm_tests.py,test_microvm_tests.py,test_nvx_tools.py}. The roadmap commit is derived again from Git: the previous pin3d7512af6is position 372, an ancestor of the new pin with no merges, which is position 378. Every commit is signed.Validation
At OpenVMM
858b2f93a(tree5d3b9c03e) and this series ondevat2266fa593(tree89916355abefore the roadmap commit), on the NVX test VMs (nvx-kvm-test,nvx-mshv-test,nvx-whp-test) unless noted.devthen gained only its performance-baseline update682a5ca4d, which changes nothing butdata/*.csv; the series rebuilt onto it is identical bygit range-diff, and its head differs from the validated tree by exactly that update and the roadmap.OpenVMM's gates (as [DO NOT REVIEW] microVM: publish the host's clock correction with each time sample openvmm#4830 reports): the changed generic packages with the backend's crate and
vmm_testspass check, clippy with-D warnings, and rustdoc on all three; unit and ignored hardware tests pass, 732 and 13 on KVM, 770 and 14 on MSHV, 698 and 19 on WHP; both microVM VMM tests pass on KVM; CI's workspace quick-check clippy passes on MSHV; andcargo xtask fmtpasses, run locally.NVX's default microVM suite, shards 1/2 and 2/2 of
scripts/nvx_tools/microvm_shards.jsonfor each backend, afternvx.py verify,build-openvmmat the pin,build-guest, and a releasenvx-rs: all 42 scenarios pass on Linux/KVM (Azure Linux 3, kernel 6.6), Linux/MSHV (kernel 6.18), and Windows/WHP (Windows Server 2025, with the KVM VM's guest artifacts,vmlinuxf7dd45ccandinitramfs.cpio.gzbc4b23be).time-host-correctionsaw the guest follow each published correction:frequency_limited=1frequency_limited=1frequency_limited=1The columns give the correction that the guest held and the rate that it measured. On MSHV, chrony steered the VM's clock, which follows Hyper-V's PTP clock, by tens of ppm within minutes: the probe read the host's own correction at -34.1 ppm, but the restore window's two samples published +53.0 and +87.8 ppm, about -131 and -96 ppm of host correction, so that phase missed its +150 ppm target although the guest held its accepted sample's correction. Three reruns of the scenario there, at host corrections of -67.1, -82.1, and -99.5 ppm, held +165.5, +128.0, and +186.6 ppm after restore and passed, as three on KVM did at +149.8, +164.4, and +148.2 ppm.
nvx-rs(check-nvx-rs): on Windows, run locally, fmt, clippy with-D warningsin its three configurations, tests with all features (1305), default (1069), and the library without default features (270), and rustdoc with-D warnings; on Linux (the MSHV VM, kernel 6.18), fmt, clippy in the three configurations, tests with all features (2099), default (1039), and the library without default features (270), artifact bundling (19), rustdoc with-D warnings, the MSRV (1.89) check, the guest binaries' lint, build, and tests (36), and the runtime adapter's protocol-only (48 tests), host-only (124), and musl guest-only (145) configurations, each with clippy, build, tests, rustdoc, and the MSRV check.Quality (check-quality):
ruff check,ruff format --check,pyrightfor Linux and Windows, and the Markdown links pass locally, and ShellCheck and shfmt pass with CI's pinned images on the KVM VM.Python (validate-nvx): the CLI suite passes on Linux (the MSHV VM: 1556 tests, 31 skipped) and on Windows (the WHP VM, Python 3.12: 1556 tests, 120 skipped), with the adversarial (84) and host-resolver (4) tests and every
nvx.pycommand's--help.At the head,
468505ed8(tree57404c586):nvx.py verifyand the Markdown links pass locally, andnvx.py verifyand the Python CLI suite (1556 tests, 31 skipped) pass again on the MSHV VM.Not run here: the macOS check of
nvx-rs, benchmarks, and the rest of NVX's CI matrix, which this draft starts once it is marked ready.Not in scope. #1018's open review thread on
time-host-correction's rate check (scripts/nvx_tools/microvm_tests.py), which can pass inconclusively when a sample's realtime bracket is wide, is carried here unchanged.This draft's head is
468505ed8cbd8ad3344aea6470a31304130967f3; as a draft it runs no NVX CI until it is marked ready.