Repository navigation
[DO NOT REVIEW] microVM: name every CPUID difference in CPU-surface errors - #4804
Merged
Pedro Henrique Penna (ppenna) merged 4 commits intoOct 30, 2026
Conversation
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 29, 2026
Pin microsoft/openvmm#4804 at 93cf08c4da393ec6879a193e300b51df409816aa, four commits on bd2b27a2e, the previous pin, which is the head of feature/microvm/dev. CPU-profile verification is to report every violation together, naming the leaf, subleaf, register, and bit, as section 2.2.1.3 of the architecture guide states. OpenVMM's E_CPU_SURFACE errors instead named at most 16 differences and dropped the rest, though they counted them all: both the restore's comparison of the recomputed effective CPUID with the snapshot's record and the comparison of VP 0's CPUID with the effective CPUID before any VP runs. The VM worker also ran its CPU checks in turn and stopped at the first that failed. The first commit names, for each entry that both the recomputed effective CPUID and the snapshot's record hold, every register in which they differ, with its value and mask on each side, on one line, rather than all four results and masks of each side as pretty-printed arrays of 24 lines. The second names every difference. The lists stay bounded: the effective CPUID of each pinned profile has between 64 and 94 entries, and a snapshot's record at most 1024, which the manifest decoder enforces. The third names the non-zero CPUID entries outside the profile's tables that VP 0 reads on a pass-through backend together with the results that VP 0 does not observe, rather than only once those match, as the support check names such entries after what a backend lacks. A report whose only violations are such entries still fails with E_CPU_UNLISTED. The fourth runs every CPU check of a partition, even after one fails: the restore's comparison with the snapshot's record, the check of VP 0's CPUID, and the check that the backend supports the profile. It reports their failures together, leading with the first failure, and so with the code that OpenVMM reported before. A failure alone is reported as before. The line with which OpenVMM exits on these errors keeps its code, from which nvx-rs attributes a clone's failure to an incompatible host. The error's detail follows that line in OpenVMM's log. For the largest pinned profile, whose effective CPUID has 94 entries, an error in which every register of every entry differs in both comparisons and the backend supports nothing takes 61,717 bytes, within the 64 KiB at the end of the log that nvx-rs searches for the line. The protocol vectors and built-in CPU profiles that nvx-rs copies are unchanged. Refs #568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 29, 2026
Record the four commits that the previous commit pins as positions 360-363 of the microVM chain, and move the NVX pin to 93cf08c4d. Positions 360-363 make the E_CPU_SURFACE errors of the microVM's CPU checks name every CPUID difference rather than the first 16, each entry of a snapshot's effective CPUID record on one line with the registers in which it differs, and name the non-zero CPUID entries outside the profile's tables that VP 0 reads together with the results that VP 0 does not observe. The VM worker then runs every CPU check of a partition, even after one fails, and reports their failures together. They change only the CPU checks of the VM worker's time ABI, which the time ABI work at positions 159-269 added; say so in the table's remarks. The pin is now 206 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#4804 as the proposal of positions 360-363. Refs #568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the effective CPUID that a restore recomputes differs from the one
that the snapshot recorded, the E_CPU_SURFACE error names each entry
that differs. For an entry that both have, it printed all four results
and masks of each side with {:#x?}, which pretty-prints each array over
six lines, so that one entry took 24 lines of the error and the reader
had to compare the arrays to find the register that differs.
Name each register in which such an entry differs instead, on one line,
with its value and mask on each side, as the check of VP 0's CPUID
names the registers of the results that VP 0 does not observe:
CPUID 0x0 EAX is 0x0000001b under mask 0xffffffff, and 0x0000001a
under mask 0xffffffff in the snapshot
An entry that only one side has is named as before. The error thus
takes one line, whatever the number of entries that it names, which the
next commit makes every differing entry rather than the first 16.
The test of the recorded CPUID now checks that a flipped bit is named
with its register, value, and mask, and that the entries of another
topology are named on one line.
Part of microsoft/nvx#568.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The CPU checks of a new partition are to report every violation together, naming the leaf, subleaf, register, and bit. Both E_CPU_SURFACE failures of the VM worker counted every difference but named at most 16 (MAX_REPORTED_CPUID_DIFFERENCES) and dropped the rest: the restore's comparison of the recomputed effective CPUID with the snapshot's record, and the comparison of VP 0's CPUID with the effective CPUID at every cold boot and restore. A host or a build that differed in more entries showed only the first 16, so a fix of those could fail again on entries that the error had not named. Name every difference. The lists stay bounded: the effective CPUID of each pinned profile has between 64 entries (Skylake-SP) and 94 (Turin), its table and the 22 topology and identity entries that OpenVMM adds, so VP 0's comparison names at most that many results. A snapshot's record holds at most MAX_EFFECTIVE_CPUID_ENTRIES (1024) entries, which the manifest decoder enforces, so the restore's comparison names at most that many more entries that only the snapshot has. The new tests make every result of a 2-VP Ice Lake-SP partition, 69 of them, differ from what VP 0 reads, and every entry from the snapshot's record, and check that the errors count and name each one, in order. Both fail with the limit restored. Part of microsoft/nvx#568. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Before any VP runs, VP 0's CPUID, as the backend reports it, must equal the effective CPUID under its masks (E_CPU_SURFACE), and, on a pass-through backend, read zero at every host entry outside the profile's tables (E_CPU_UNLISTED). check_presented checked the second only once the first had passed, so a report that failed both named the results that VP 0 does not observe but none of the non-zero entries outside the profile, which surfaced only once the results were fixed. Name them together, as cpu_profile::verify_support names the non-zero entries outside the profile after the features, limits, and layouts that a backend lacks: an E_CPU_SURFACE failure names every result that VP 0 does not observe, then every non-zero entry outside the profile's tables, and a report whose only violations are such entries still fails with E_CPU_UNLISTED. No failure changes its code, so callers that match the code see the same one as before. The test of the entries outside the profile now drops two governed results from a report that also reads a non-zero entry past Ice Lake-SP's maximum basic leaf, and checks that the error names both results and then the entry. Part of microsoft/nvx#568. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ogether At every cold boot and restore, before any VP runs, the VM worker checks the partition's CPU against its CPU profile in three steps: on restore, that the effective CPUID it recomputes is the one that the snapshot recorded (E_CPU_SURFACE); that VP 0 observes the effective CPUID (E_CPU_SURFACE, or E_CPU_UNLISTED for a non-zero entry outside the profile's tables); and that the backend supports the profile (E_PROFILE_UNSUPPORTED). Each check names every violation that it finds, but the worker ran them in turn and stopped at the first that failed. A restore whose record differed therefore did not say whether VP 0 also read other values or the host also lacked a feature of the profile, which surfaced only once the first failure was fixed. Run every check and report their failures together, as CPU-profile verification is to report every violation together. check_cpu_profile runs the three checks in that order, even after one fails. report_together returns the failure of a check that fails alone unchanged, so that its type and code are what they were, and otherwise one error that gives each failure's chain in turn, joined with "; ". Such an error leads with the first failure, and so with the code that the worker reported before: the process's exit line, the hints of --cpu-profile auto, and petri's host-profile fallback all take the first bracketed code of the error chain. A partition without a time ABI backend fails both of the backend's checks with that failure, after any failure of the snapshot's record. The log line of checks that pass, with their timings, moves into check_cpu_profile. The error, which follows OpenVMM's exit line in its log, stays bounded: for the largest pinned profile, Turin, whose effective CPUID has 94 entries, an error in which every register of every entry differs in both comparisons and the backend supports nothing takes 61,717 bytes, on one line. The new test fails the snapshot's record, VP 0's view, and the backend's support of a 2-VP Ice Lake-SP partition, alone and in every combination, and runs a partition without a time ABI backend. It checks the combined errors and their leading code, and that a failure alone is the check's own error. It fails if the checks stop at the first failure. The Guide's snapshot page says that the checks report together. Part of microsoft/nvx#568. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
copilot/microvm-cpu-surface-every-difference
branch
from
October 29, 2026 21:31
93cf08c to
e4c741e
Compare
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 29, 2026
Pin microsoft/openvmm#4804 at e4c741e1860de1e2149b3dd5d41863468705b02c, four commits on c32c57d12, the previous pin, which is the head of feature/microvm/dev. CPU-profile verification is to report every violation together, naming the leaf, subleaf, register, and bit, as section 2.2.1.3 of the architecture guide states. OpenVMM's E_CPU_SURFACE errors instead named at most 16 differences and dropped the rest, though they counted them all: both the restore's comparison of the recomputed effective CPUID with the snapshot's record and the comparison of VP 0's CPUID with the effective CPUID before any VP runs. The VM worker also ran its CPU checks in turn and stopped at the first that failed. The first commit names, for each entry that both the recomputed effective CPUID and the snapshot's record hold, every register in which they differ, with its value and mask on each side, on one line, rather than all four results and masks of each side as pretty-printed arrays of 24 lines. The second names every difference. The lists stay bounded: the effective CPUID of each pinned profile has between 64 and 94 entries, and a snapshot's record at most 1024, which the manifest decoder enforces. The third names the non-zero CPUID entries outside the profile's tables that VP 0 reads on a pass-through backend together with the results that VP 0 does not observe, rather than only once those match, as the support check names such entries after what a backend lacks. A report whose only violations are such entries still fails with E_CPU_UNLISTED. The fourth runs every CPU check of a partition, even after one fails: the restore's comparison with the snapshot's record, the check of VP 0's CPUID, and the check that the backend supports the profile. It reports their failures together, leading with the first failure, and so with the code that OpenVMM reported before. A failure alone is reported as before. The line with which OpenVMM exits on these errors keeps its code, from which nvx-rs attributes a clone's failure to an incompatible host. The error's detail follows that line in OpenVMM's log. For the largest pinned profile, whose effective CPUID has 94 entries, an error in which every register of every entry differs in both comparisons and the backend supports nothing takes 61,717 bytes, within the 64 KiB at the end of the log that nvx-rs searches for the line. The protocol vectors and built-in CPU profiles that nvx-rs copies are unchanged. Refs #568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 29, 2026
Record the four commits that the previous commit pins as positions 362-365 of the microVM chain, and move the NVX pin to e4c741e18. Positions 362-365 make the E_CPU_SURFACE errors of the microVM's CPU checks name every CPUID difference rather than the first 16, each entry of a snapshot's effective CPUID record on one line with the registers in which it differs, and name the non-zero CPUID entries outside the profile's tables that VP 0 reads together with the results that VP 0 does not observe. The VM worker then runs every CPU check of a partition, even after one fails, and reports their failures together. They change only the CPU checks of the VM worker's time ABI, which the time ABI work at positions 159-269 added, and the snapshot guide's description of them; say so in the table's remarks. The pin is now 208 commits past the mapped tip. Positions 360 and 361 are no longer only a proposal: microsoft/openvmm#4807 merged them, so position 361, c32c57d12, is the head of feature/microvm/dev. Say so in the scope, and name microsoft/openvmm#4804 as the proposal of positions 362-365. Refs #568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 29, 2026
Pin microsoft/openvmm#4804 at e4c741e1860de1e2149b3dd5d41863468705b02c, four commits on c32c57d12, the previous pin, which is the head of feature/microvm/dev. CPU-profile verification is to report every violation together, naming the leaf, subleaf, register, and bit, as section 2.2.1.3 of the architecture guide states. OpenVMM's E_CPU_SURFACE errors instead named at most 16 differences and dropped the rest, though they counted them all: both the restore's comparison of the recomputed effective CPUID with the snapshot's record and the comparison of VP 0's CPUID with the effective CPUID before any VP runs. The VM worker also ran its CPU checks in turn and stopped at the first that failed. The first commit names, for each entry that both the recomputed effective CPUID and the snapshot's record hold, every register in which they differ, with its value and mask on each side, on one line, rather than all four results and masks of each side as pretty-printed arrays of 24 lines. The second names every difference. The lists stay bounded: the effective CPUID of each pinned profile has between 64 and 94 entries, and a snapshot's record at most 1024, which the manifest decoder enforces. The third names the non-zero CPUID entries outside the profile's tables that VP 0 reads on a pass-through backend together with the results that VP 0 does not observe, rather than only once those match, as the support check names such entries after what a backend lacks. A report whose only violations are such entries still fails with E_CPU_UNLISTED. The fourth runs every CPU check of a partition, even after one fails: the restore's comparison with the snapshot's record, the check of VP 0's CPUID, and the check that the backend supports the profile. It reports their failures together, leading with the first failure, and so with the code that OpenVMM reported before. A failure alone is reported as before. The line with which OpenVMM exits on these errors keeps its code, from which nvx-rs attributes a clone's failure to an incompatible host. The error's detail follows that line in OpenVMM's log. For the largest pinned profile, whose effective CPUID has 94 entries, an error in which every register of every entry differs in both comparisons and the backend supports nothing takes 61,717 bytes, within the 64 KiB at the end of the log that nvx-rs searches for the line. The protocol vectors and built-in CPU profiles that nvx-rs copies are unchanged. Refs #568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 29, 2026
Record the four commits that the previous commit pins as positions 362-365 of the microVM chain, and move the NVX pin to e4c741e18. Positions 362-365 make the E_CPU_SURFACE errors of the microVM's CPU checks name every CPUID difference rather than the first 16, each entry of a snapshot's effective CPUID record on one line with the registers in which it differs, and name the non-zero CPUID entries outside the profile's tables that VP 0 reads together with the results that VP 0 does not observe. The VM worker then runs every CPU check of a partition, even after one fails, and reports their failures together. They change only the CPU checks of the VM worker's time ABI, which the time ABI work at positions 159-269 added, and the snapshot guide's description of them; say so in the table's remarks. The pin is now 208 commits past the mapped tip. Positions 360 and 361 are no longer only a proposal: microsoft/openvmm#4807 merged them, so position 361, c32c57d12, is the head of feature/microvm/dev. Say so in the scope, and name microsoft/openvmm#4804 as the proposal of positions 362-365. Refs #568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
merged commit Oct 30, 2026
e4c741e
into
feature/microvm/dev
105 of 108 checks passed
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 30, 2026
… roadmap Record the two commits that the previous commit pins as positions 368 and 369 of the microVM chain, and move the NVX pin to 6b409bd10. Position 368 makes the change of microsoft/openvmm#4803 unchanged: the KVP IC test boots Windows Server 2025 instead of 2022, whose COM activation race can fail the guest's answer to the test's IP information request. Position 369 stages the Server 2025 image for the check-in gates' x64 Linux KVM job. It excludes the test and its image from the MSHV job, where Server 2025's required initial reset fails. A rebase onto an upstream main that includes microsoft/openvmm#4803 drops position 368 and reconciles position 369 with upstream's changes for those jobs; say so in the table's remarks. The pin is now 212 commits past the mapped tip. Keep the re-checked chain in the scope: microsoft/openvmm#4807 merged positions 360 and 361, microsoft/openvmm#4804 merged positions 362-365, and microsoft/openvmm#4818 merged positions 366 and 367. Position 367, bcfc47cff, is therefore the head of feature/microvm/dev, and microsoft/openvmm#4816 proposes positions 368 and 369. Refs #1035 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 30, 2026
… roadmap Record the two commits that the previous commit pins as positions 368 and 369 of the microVM chain, and move the NVX pin to 6b409bd10. Position 368 makes the change of microsoft/openvmm#4803 unchanged: the KVP IC test boots Windows Server 2025 instead of 2022, whose COM activation race can fail the guest's answer to the test's IP information request. Position 369 stages the Server 2025 image for the check-in gates' x64 Linux KVM job. It excludes the test and its image from the MSHV job, where Server 2025's required initial reset fails. A rebase onto an upstream main that includes microsoft/openvmm#4803 drops position 368 and reconciles position 369 with upstream's changes for those jobs; say so in the table's remarks. The pin is now 212 commits past the mapped tip. Keep the re-checked chain in the scope: microsoft/openvmm#4807 merged positions 360 and 361, microsoft/openvmm#4804 merged positions 362-365, and microsoft/openvmm#4818 merged positions 366 and 367. Position 367, bcfc47cff, is therefore the head of feature/microvm/dev, and microsoft/openvmm#4816 proposes positions 368 and 369. Refs #1035 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 30, 2026
… roadmap Record the two commits that the previous commit pins as positions 368 and 369 of the microVM chain, and move the NVX pin to 6b409bd10. Position 368 makes the change of microsoft/openvmm#4803 unchanged: the KVP IC test boots Windows Server 2025 instead of 2022, whose COM activation race can fail the guest's answer to the test's IP information request. Position 369 stages the Server 2025 image for the check-in gates' x64 Linux KVM job. It excludes the test and its image from the MSHV job, where Server 2025's required initial reset fails. A rebase onto an upstream main that includes microsoft/openvmm#4803 drops position 368 and reconciles position 369 with upstream's changes for those jobs; say so in the table's remarks. The pin is now 212 commits past the mapped tip. Keep the re-checked chain in the scope: microsoft/openvmm#4807 merged positions 360 and 361, microsoft/openvmm#4804 merged positions 362-365, and microsoft/openvmm#4818 merged positions 366 and 367. Position 367, bcfc47cff, is therefore the head of feature/microvm/dev, and microsoft/openvmm#4816 proposes positions 368 and 369. Refs #1035 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CaffeeLake (CaffeeLake)
pushed a commit
to CaffeeLake/nvx
that referenced
this pull request
Oct 30, 2026
A clone whose VMM exits before its restore-ready event reads, from the VMM's log, the line with which OpenVMM reported the error that ended it, and attributes the failure to an incompatible host when the line's time ABI code, such as E_CPU_SURFACE, says so. OpenVMM writes that line first, then the error's chain. read_fatal looked for the line in the last 64 KiB of the log alone, which held it while OpenVMM's CPU checks named at most 16 differences. Since microsoft/openvmm#4804, which microsoft#1014 pinned, they name every difference that they find, together, in one cause of the chain: about 7.5 KB on the Azure test hosts, and 61,717 bytes for the Turin profile when every register of every entry differs in both comparisons and the backend supports none of the profile, but more for a pass-through backend whose VP 0 reads non-zero values at entries outside the profile's tables, each of which the error names, or for a snapshot record of up to the 1024 entries that the decoder admits. A chain longer than 64 KiB pushed the line out of the tail, so the failure kept its lost status, whose outcome is unknown, rather than the incompatible host, and lost OpenVMM's line from its message. read_fatal now reads the log back from its end, 64 KiB at a time, until it finds the last line that starts with "fatal error: ", then reads that line and the chain that follows it, so that the line keeps its attribution after a chain of any length. A log without the line is read whole, a block at a time. Tests check that the line is read before a chain several blocks long, whether or not a line precedes it, with a cause that names a forward that OpenVMM cannot bind after a long one, and wherever a block starts around the line: after the newline before it, at its start, or within its prefix; and that a long log that only quotes the line holds none. Follow-up to microsoft#568. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CaffeeLake (CaffeeLake)
pushed a commit
to CaffeeLake/nvx
that referenced
this pull request
Oct 30, 2026
Record the two commits that the previous commit pins as positions 366 and 367 of the microVM chain, and move the NVX pin to bcfc47cff. Positions 366 and 367 make the restore's comparison of the effective CPUID with a snapshot's record name every difference of a record that the decoder admits although no OpenVMM writes it: each entry that the record lists more than once, each of its listings that differs, and a record out of order, together with the entries that differ. They also test each register, value, and mask that the error names. They change only the first CPU check of the VM worker's time ABI, its tests, and the snapshot guide's description of it; say so in the table's remarks. The pin is now 210 commits past the mapped tip. Positions 362-365 are no longer only a proposal: microsoft/openvmm#4804 merged them, so position 365, e4c741e18, is the head of feature/microvm/dev. Say so in the scope, and name microsoft/openvmm#4818 as the proposal of positions 366 and 367. Refs microsoft#568 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
added a commit
to microsoft/nvx
that referenced
this pull request
Oct 30, 2026
… roadmap Record the two commits that the previous commit pins as positions 370 and 371 of the microVM chain, and move the NVX pin to 549a21512. Position 370 makes the change of microsoft/openvmm#4803 unchanged: the KVP IC test boots Windows Server 2025 instead of 2022, whose COM activation race can fail the guest's answer to the test's IP information request. Position 371 stages the Server 2025 image for the check-in gates' x64 Linux KVM job. It excludes the test and its image from the MSHV job, where Server 2025's required initial reset fails. A rebase onto an upstream main that includes microsoft/openvmm#4803 drops position 370 and reconciles position 371 with upstream's changes for those jobs; say so in the table's remarks. The pin is now 214 commits past the mapped tip. Keep the re-checked chain in the scope: microsoft/openvmm#4807 merged positions 360 and 361, microsoft/openvmm#4804 merged positions 362-365, microsoft/openvmm#4818 merged positions 366 and 367, and microsoft/openvmm#4820 merged positions 368 and 369. Position 369, 5e0ab772e, is therefore the head of feature/microvm/dev, and microsoft/openvmm#4816 proposes positions 370 and 371. Refs #1035 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.
Names every difference in the
E_CPU_SURFACEerrors of the microVM's CPU checks, and reports the failures of every CPU check of a partition together, for microsoft/nvx#568. The VM worker counted every CPUID difference but named at most 16 and dropped the rest, both when a restore compares the effective CPUID that it recomputes with the snapshot's record and when the worker compares VP 0's CPUID with the effective CPUID before any VP runs. It also stopped at the first of its CPU checks that failed. It now names each difference, each recorded entry on one line with the registers in which it differs, and reports the non-zero CPUID entries outside the profile's tables that VP 0 reads together with the results that VP 0 does not observe. It runs every check even after one fails, and reports their failures in one error that leads with the first.Based on
feature/microvm/dev. This branch is four commits directly onc32c57d12, the head offeature/microvm/devsince #4807 merged, which microsoft/nvx'sdevpins. It was rebased there frombd2b27a2ewhen #4807 merged, andgit range-diffshows its four commits unchanged. microsoft/nvx#1014 pins this branch's head.Why
Section 2.2.1.3 of the NVX architecture guide states that CPU-profile verification reports every violation together, naming the leaf, subleaf, register, and bit.
check_recorded_cpuidandcheck_presentedappliedMAX_REPORTED_CPUID_DIFFERENCES(16), so a build or host that differed in more entries showed the first 16, and a fix of those could fail again on entries that the error had not named. The restore's comparison also printed each differing entry's four results and masks on each side with{:#x?}, which pretty-prints every array over six lines: 24 lines per entry, without saying which register differs, which listing every entry would have multiplied. And the worker ran its three checks in turn, each with?, so a restore whose record differed did not say whether VP 0 also read other values or the backend also lacked a feature of the profile, which surfaced only once the first failure was fixed.Registers of a recorded entry (
69ddc715b)For an entry that both the recomputed effective CPUID and the snapshot's record hold,
recorded_cpuid_differencesnames each register in which they differ, with its value and mask on each side, on one line, ascpuid_differencesnames the registers of the results that VP 0 does not observe:An entry that only one side has is named as before.
Every difference (
c55db5d9e)Both errors name every difference and keep counting them. The lists stay bounded: the effective CPUID of each pinned profile has between 64 entries (Skylake-SP) and 94 (Turin), its table and the 22 topology and identity entries that OpenVMM adds, so VP 0's comparison names at most that many results, and a snapshot's record holds at most
MAX_EFFECTIVE_CPUID_ENTRIES(1024), which the manifest decoder enforces, so the restore's comparison names at most that many more entries that only the snapshot has.Entries outside the profile with VP 0's differences (
e1fa0f028)check_presentedchecked VP 0's view at the host's entries outside the profile's tables (E_CPU_UNLISTED) only once VP 0 observed every result, so a report that failed both named the results but none of those entries. It now names them together, ascpu_profile::verify_supportnames the entries outside the profile after what a backend lacks: anE_CPU_SURFACEfailure names every result that VP 0 does not observe, then every non-zero entry outside the profile's tables, and a report whose only violations are such entries still fails withE_CPU_UNLISTED. No failure changes its code.Every check's failures together (
e4c741e18)check_cpu_profileruns the worker's three CPU checks in order, each even after an earlier one fails: on restore, the comparison of the recomputed effective CPUID with the snapshot's record; then the check of VP 0's CPUID; then the check that the backend supports the profile.report_togetherreturns a failure that occurs alone unchanged, so that its type and code stay what they were, and combines several into one error that gives each failure's chain in turn, joined with;, as a restore on Linux/KVM shows it:The error leads with the first failure, and so with the code that the worker reported before: the exit line, the hints of
--cpu-profile auto(hint_host_profile), and petri's host-profile fallback all take the first bracketed code of the chain. A partition without a time ABI backend fails both of the backend's checks with that failure, after any failure of the snapshot's record. Thetime ABI CPU checks passedlog line, with the checks' timings, moves intocheck_cpu_profile, so its target is nowopenvmm_core::worker::dispatch::time_abi. The Guide's snapshot page says that the checks report together.The error stays bounded. For Turin, the largest pinned profile, an error in which every register of all 94 entries differs in both comparisons and the backend supports nothing takes 61,717 bytes, on one line: 37,223 for the record, 22,815 for VP 0's view, and 1,675 for the support check. Skylake-SP's takes 41,854. These figures come from a scratch test over every pinned profile, which is not part of this branch.
The other checks
The checks themselves name every violation:
cpu_profile::verify_supportevery feature, limit, XSAVE layout, address width, and MSR value that a backend lacks (E_PROFILE_UNSUPPORTED), and, for a fingerprint's probe partition, every non-zero entry outside the profile;hv_banks::profile_featuresevery feature that MSHV's and WHP's processor feature banks lack; andcpu_profile::check_unlisted_cpuidevery non-zero entry outside the profile (E_CPU_UNLISTED). The generation check, and a restore's checks of the profile's ID, digest, and document, each have a single violation, and run before the partition exists, which the other checks need. MSHV and WHP refuse a profile feature that their processor feature banks lack when they create the partition, also before these checks run. The backends' time ABI preflight, which checks the identity leaves, the CPU time bits, and, on WHP, that the processor feature banks hide the timer features, enforces the backend obligations of section 3.2.6 of the guide rather than these steps, and still fails at its first violation.Tests
recorded_cpuid_must_match: a flipped bit is named with its register, value, and mask, and the entries of another topology are named on one line.recorded_cpuid_names_every_differenceandpresented_cpuid_names_every_difference: every entry of a 2-VP Ice Lake-SP partition's record, and every one of its 69 results, differs, and the errors count and name each one, in order. Both fail with the limit restored.presented_cpuid_rejects_non_zero_unlisted_entries: a report that drops two governed results and reads a non-zero entry past Ice Lake-SP's maximum basic leaf fails withE_CPU_SURFACE, naming both results and then the entry. It fails if the entry is left out.cpu_checks_report_every_failure_together: with a fake time ABI backend, a 2-VP Ice Lake-SP partition whose snapshot record differs in one entry, whose VP 0 does not observe the brand string's first leaf, and whose backend lacks AVX2, alone and in every combination, and a partition without a time ABI backend. It checks the combined errors and their leading code, and that a failure alone is the check's own error, down to theProfileErrorof the support check. It fails if the checks stop at the first failure.Validation
On this branch, on Windows: for
openvmm_core,cargo clippy --all-targets -- -D warnings,cargo doc --no-deps, andcargo nextest run --profile agentate4c741e18(121 tests passed), withcpu_profile's 119, andcargo xtask fmt, all clean. Before the rebase, the first three commits passed 118, 120, and 120 tests onbd2b27a2e.End to end on NVX's Azure test VMs, with openvmm: name every CPUID difference in CPU-surface errors nvx#1014's head, which pins this branch, and the guest artifacts of NVX release
v0.1.0-dev.299d0b4d9851, whose OpenVMM,bd2b27a2e, served as the baseline:Several failures. On Linux/KVM (Xeon Platinum 8573C), a snapshot that this branch captured on the host profile
intel.host.v1(--cpu-profile host), whose profile document in the manifest then had SSE4A (CPUID0x80000001ECX bit 6), which Intel CPUs lack, set and its digest updated, fails to restore on each binary with the same exit line,fatal error: [E_CPU_SURFACE] failed to launch vm worker. This branch names both failures, as shown above;235da5cb8, this branch's third commit before the rebase, names the record's difference alone, and the baseline names it over 24 lines. MSHV and WHP refuse such a profile when they create the partition, before these checks run ([E_PROFILE_UNSUPPORTED] the hypervisor's processor features cannot present CPU profile intel.host.v1: they lack sse4a_support), on this branch as before.Every difference. A snapshot that this branch captured, whose manifest's effective CPUID record then had bit 0 of EAX flipped in every entry, fails to restore on both binaries with the same exit line,
fatal error: [E_CPU_SURFACE] failed to launch vm worker. The baseline counts every entry but names 16, over 321 lines; this branch names each one, on one line, and no other failure, as the other checks, which now run too, pass:intel.emeraldrapids.v1intel.emeraldrapids.v1intel.icelake-sp.v1NVX's microVM scenarios
smp-snapshot(1, 2, 4, and 8 vCPUs),snapshot-core, andtime-abi-conformance(8 vCPUs), whose cold boots and restores pass every CPU check, pass ate4c741e18, as they did at93cf08c4dbefore the rebase, on Linux/KVM, Linux/MSHV, and Windows/WHP on those VMs, and a--x-time-abi-verifycold boot on each logstime ABI CPU checks passedwith the checks' timings.CI: every check passed at
e4c741e18, OpenVMM's VMM tests included, which ran only there. The first attempt of run 40958505253 failed its twoverify openhcl binary sizejobs: they compare with thefeature/microvm/devCI run ofc32c57d12, which was still running, and their rerun passed once it completed.Notes