Repository navigation
openvmm: verify pinned CPU profiles at partition creation - #1016
Merged
Pedro Henrique Penna (ppenna) merged 2 commits intoOct 29, 2026
Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
Pedro Henrique Penna (ppenna) merged 2 commits into
Conversation
Pin microsoft/openvmm#4807 at c32c57d129a36fc8c82308d6659f8d7ab5955474, two commits on bd2b27a2e, the previous pin, which is the head of feature/microvm/dev since microsoft/openvmm#4794 merged. At partition creation, for cold boot and restore, step 1 of the CPU profile verification in section 2.2.1.3 of the architecture guide requires the VMM to verify that the CPU profile is valid, including its canonical encoding, density, ownership masks, and CPU time bits. OpenVMM did so for host profiles, but built each pinned profile from the constants of pinned_data.rs on first use without validating or encoding it, so a stale or malformed pinned_data.rs reached partition creation unchecked; only the catalog's tests would have caught it. Its profile validation did not check the CPU time bits either, so the host profile document that a snapshot carries did not have to fix them on KVM and MSHV, whose preflights, unlike WHP's, do not check the time bits that the backend presents. The first commit adds the CPU time bits of section 3.2.3 to profile validation, naming every bit that violates them, so that decoding a host profile document that violates them, and so restoring its snapshot, fails with E_PROFILE_DIGEST. The second verifies each pinned profile once per process, on its first use: its built-in values must form a valid profile, CPU time bits included, whose canonical encoding is the built-in encoding that snapshots embed. A defective profile fails the cold boot or restore that selects it with E_PROFILE_DIGEST, before the partition exists. The verification encodes the profile but does not hash it: its digest stays a constant that OpenVMM's tests check against the golden digests. It adds about 40 to 55 us to the first profile use of each OpenVMM process, which NVX's single-process OpenVMM makes once per cold boot or restore, on current hosts, and 40 to 180 us on Skylake-SP hosts. The protocol vectors and built-in CPU profiles that nvx-rs copies are unchanged. Refs #567 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Record the two commits that the previous commit pins as positions 360 and 361 of the microVM chain, and move the NVX pin to c32c57d12. Positions 360 and 361 verify CPU profiles as the architecture guide's partition-creation checks require: profile validation checks the CPU time bits, so a snapshot's host profile document must fix them too, and the catalog verifies each pinned profile once per process, before a partition uses it, while the tests keep checking the golden digests. They change only cpu_profile, the fork's CPU profile crate that positions 159-269 add, a test helper of virt_mshv, and the snapshot guide, so they build on that fork-only code; say so in the table's remarks. The pin is now 204 commits past the mapped tip. Positions 355-359 are no longer only a proposal: microsoft/openvmm#4794 merged them, so position 359, bd2b27a2e, is the head of feature/microvm/dev. Say so in the scope, and name microsoft/openvmm#4807 as the proposal of positions 360 and 361. Refs #567 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
CPU-profile validation changes span cold boot and restore across three backends, with exact-head CI, WHP and corrupted-profile validation, and prerequisite upstream landing still pending.
No open issues 🎉
What changed in this PR
This PR promotes an OpenVMM revision that validates pinned CPU profiles before partition creation for cold boot and restore, addressing #567. The roadmap documents the new pin and its upstream dependencies.
Changes:
- Updates the documented NVX pin to
c32c57d12at position 361. - Records CPU time-bit validation and once-per-process pinned-profile verification at positions 360–361.
- Updates chain counts and records the merge of OpenVMM #4794.
| File | Description |
|---|---|
doc/openvmm-upstream-roadmap.md |
Updates the pin, commit-chain diagram, and roadmap entries for CPU-profile validation. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
deleted the
agents/issue-567-validate-pinned-cpu-profiles
branch
October 29, 2026 20:11
This was referenced Oct 29, 2026
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 #567. Pins microsoft/openvmm#4807 at
c32c57d129a36fc8c82308d6659f8d7ab5955474, which verifies each pinned CPU profile before a partition uses it, as step 1 of section 2.2.1.3 of the architecture guide requires at partition creation, for cold boot and restore: once per process, the profile that OpenVMM builds from its built-in data must be valid, with its density, ownership masks, and CPU time bits, and its built-in encoding, which snapshots embed, must be its canonical encoding. Profile validation also gains the CPU time bits of section 3.2.3, so the host profile document that a snapshot carries must fix them too.Based on
devat67f395e54. microsoft/openvmm#4807 is two commits directly onbd2b27a2e, the head offeature/microvm/devand the revision thatdevpins since #974 merged, and the pin is that pull request's head commit itself, so this branch's two commits are its whole diff.Change
7f15ed6f1openvmmopenvmmbd2b27a2e→c32c57d12: the two commits of microsoft/openvmm#48075be4850e8docdoc/openvmm-upstream-roadmap.mdcpu_profilecrate; moves the NVX pin; and records that microsoft/openvmm#4794 merged positions 355-359 intofeature/microvm/devNo other NVX change is needed: OpenVMM's control-session protocol vectors and built-in CPU profiles are unchanged at the pin, and section 2.2.1.3 already says what OpenVMM now verifies.
OpenVMM changes
c9ac93a63).CpuProfile::validate, which every way to build or decode a profile runs, checks every bit of Table 3.8: the hypervisor, TSC, and RDTSCP bits set; ARAT alone in leaf0x6and the invariant TSC alone in leaf0x80000007; no TSC-deadline timer, PDCM, orIA32_TSC_ADJUST; and leaves0xa,0x15, and0x16zero. It names every violating bit by leaf, subleaf, register, and bit. Before, only WHP's preflight checked the time bits, on the CPUID that the backend presents, so on KVM and MSHV a snapshot's host profile document did not have to fix them; now decoding such a document, and so its restore, fails withE_PROFILE_DIGEST. Every pinned and derived profile complies.c32c57d12). The catalog built a pinned profile frompinned_data.rson first use with "no parsing, no validation, and no hashing, which the tests do for every pinned profile instead".PinnedProfile::verifynow checks that the built profile is valid, time bits included, and that the built-in encoding is its canonical encoding, and the catalog runs it once per process, on the profile's first use, and hands out only verified profiles:select(cold boot, and the VM worker's restore),pinned_for_restore(the restore preflight),pinned, andPartitionProfile::pinnedfail withE_PROFILE_DIGESTfor a defective profile, naming it and what is wrong, before the partition exists.select_autoverifies only the revision that it selects.Design choice and cost
The issue offered to verify each pinned profile when it is first loaded, measuring the cold-boot cost, or to state that the build and tests verify pinned profiles. This verifies at first load exactly what step 1 lists: validity and the canonical encoding. The digest, which step 4 compares on restore, stays a built-in constant that OpenVMM's tests check against the golden digests, as they check the static data against the reviewed JSON files, so a pinned profile's cold boot and restore still parse no JSON and hash nothing. Hashing the 9 KB encoding at every start would have nearly doubled the cost on CPUs without the SHA extensions, such as the Skylake-SP of the benchmark hosts.
Verification adds to the first profile use of each OpenVMM process, which NVX's
--single-processOpenVMM makes once per cold boot or restore. Medians of the firstselectorpinned_for_restorein fresh processes of a release build, for the Skylake-SP, Ice Lake-SP, and Genoa profiles; the "warmed" runs busy-wait 100 ms first, so that the clock is up, as after the work that precedes selection in a starting OpenVMM:nvx-whp-test, Azure VM, Windowsprometheus32, bare metal, Linuxprometheus28, bare metal, WindowsValidation and the encoding take about a third and two thirds of it. NVX's restores take 36-200 ms and its cold starts 275-720 ms in the current baselines, so the added cost is a fraction of a percent of either.
Validation
NVX's default microVM suite with this pin, run by
test-microvmafterbuild-openvmm, with the guest artifacts ofv0.1.0-dev.299d0b4d9851. Every scenario cold boots with--cpu-profile auto, which selects the host's pinned profile, many capture and restore, andcpu-profile-fallbackcaptures and restores a host profile. Each run executed 47 scenarios, 41 distinct ones, and all passed, as did the teardown:prometheus32, bare metal with a Xeon Silver 4114 (intel.skylake-sp.v1), at this pull request's head5be4850e8and so at the pin itself.nvx-kvm-test, an Azure VM with a Xeon Platinum 8573C (intel.emeraldrapids.v1).prometheus30, bare metal with a Xeon Silver 4114 (intel.skylake-sp.v1).nvx-whp-test, an Azure VM with a Xeon Platinum 8370C (intel.icelake-sp.v1).The last three ran OpenVMM
0565b55bc, which differs from the pin only in its commit message: both have tree96769697845a.Defective built-in data, on
nvx-kvm-testwith OpenVMM0565b55bc. Each defect was built into this pin and into the previous one. A good build captured a snapshot, which the defective build then restored, and the defective build cold booted:CPUID.1:ECX[24], in the values ofintel.emeraldrapids.v1but not in its encoding, as a hand edit that forgets the encoding would. With this pin, the restore and the cold boot each fail within 0.01 s with[E_PROFILE_DIGEST] pinned CPU profile intel.emeraldrapids.v1 is invalid: it violates the CPU time bits: CPUID 0x1 ECX bit 24 is set. The previous pin only fails later, at the backend support check, withE_PROFILE_UNSUPPORTED, and suggests--cpu-profile host.CPUID.(7,0):EBX[9], in the values but not in the encoding, as a stalepinned_data.rswould. The values remain a valid profile that every backend supports. With this pin, the restore and the cold boot each fail with[E_PROFILE_DIGEST] pinned CPU profile intel.emeraldrapids.v1 differs from its constant canonical encoding. The previous pin passesguest-bootandsnapshot-core: its guest has no ERMS, but its snapshots record a profile that has it.OpenVMM at the pinned tree, on Windows with Rust 1.95.0:
cargo clippy --all-targets -- -D warningsforcpu_profile,virt,virt_whp,openvmm_helpers,openvmm_core,hypervisor_resources,openvmm_hypervisors,openvmm_entry, andpetri;cargo doc --no-deps -p cpu_profile;cargo nextest run --profile agentforcpu_profile(119 passed) and, onnvx-whp-test, forcpu_profile,virt,virt_whp,openvmm_helpers, andopenvmm_core(460 passed, 18 skipped); andcargo xtask fmt --fix(clean). On Linux: the same clippy set plusvirt_kvmandvirt_mshv(clean), and nextest forcpu_profile,virt,virt_kvm,virt_mshv,openvmm_helpers, andopenvmm_core(541 passed, 26 skipped).NVX at
5be4850e8:python scripts\nvx.py verify(consistent); theopenvmm_vectorsandopenvmm_cpu_profilescomparisons with--ignored(3 and 1 passed), against the pinned revision;python scripts\check_markdown_links.py; andgit diff --check.Every commit is signed and verified, both these and [DO NOT REVIEW] cpu_profile: verify pinned CPU profiles at partition creation openvmm#4807's.
CI: this pull request's run at
5be4850e8passed. [DO NOT REVIEW] cpu_profile: verify pinned CPU profiles at partition creation openvmm#4807's checks atc32c57d12all passed, its VMM tests on Linux (KVM, MSHV, and SNP on MSHV) and Windows (Intel, AMD, SNP, TDX, and Arm64 hosts) included.Merge [DO NOT REVIEW] cpu_profile: verify pinned CPU profiles at partition creation openvmm#4807 into
feature/microvm/dev, by fast-forwarding that branch toc32c57d12, before merging this pull request.