Skip to content

[DO NOT REVIEW] microVM: name every CPUID difference in CPU-surface errors - #4804

Merged
Pedro Henrique Penna (ppenna) merged 4 commits into
feature/microvm/devfrom
copilot/microvm-cpu-surface-every-difference
Oct 30, 2026
Merged

Pedro Henrique Penna (ppenna) merged 4 commits into
feature/microvm/devfrom
copilot/microvm-cpu-surface-every-difference

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Names every difference in the E_CPU_SURFACE errors 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 on c32c57d12, the head of feature/microvm/dev since #4807 merged, which microsoft/nvx's dev pins. It was rebased there from bd2b27a2e when #4807 merged, and git range-diff shows 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_cpuid and check_presented applied MAX_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_differences names each register in which they differ, with its value and mask on each side, on one line, as cpuid_differences 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.

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_presented checked 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, as cpu_profile::verify_support names the entries outside the profile after what 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.

Every check's failures together (e4c741e18)

check_cpu_profile runs 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_together returns 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:

fatal error: [E_CPU_SURFACE] failed to launch vm worker

Caused by:
    0: failed to launch worker
    1: [E_CPU_SURFACE] the effective CPUID of CPU profile intel.host.v1 differs from the snapshot's in 1 entries: CPUID 0x80000001 ECX is 0x00000161 under mask 0xffffffff, and 0x00000121 under mask 0xffffffff in the snapshot; [E_PROFILE_UNSUPPORTED] the backend does not support CPU profile intel.host.v1: CPUID 0x80000001 ECX bit 6 is not supported

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. The time ABI CPU checks passed log line, with the checks' timings, moves into check_cpu_profile, so its target is now openvmm_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_support every 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_features every feature that MSHV's and WHP's processor feature banks lack; and cpu_profile::check_unlisted_cpuid every 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_difference and presented_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 with E_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 the ProfileError of 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, and cargo nextest run --profile agent at e4c741e18 (121 tests passed), with cpu_profile's 119, and cargo xtask fmt, all clean. Before the rebase, the first three commits passed 118, 120, and 120 tests on bd2b27a2e.

  • 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 (CPUID 0x80000001 ECX 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:

      Backend Host CPU CPU profile Entries Baseline names This branch names
      Linux/KVM Xeon Platinum 8573C intel.emeraldrapids.v1 68 16 (6.9 KB, 321 lines) 68 (7.4 KB, 1 line)
      Linux/MSHV Xeon Platinum 8573C intel.emeraldrapids.v1 68 16 (6.9 KB, 321 lines) 68 (7.4 KB, 1 line)
      Windows/WHP Xeon Platinum 8370C intel.icelake-sp.v1 69 16 (6.9 KB, 321 lines) 69 (7.5 KB, 1 line)
  • NVX's microVM scenarios smp-snapshot (1, 2, 4, and 8 vCPUs), snapshot-core, and time-abi-conformance (8 vCPUs), whose cold boots and restores pass every CPU check, pass at e4c741e18, as they did at 93cf08c4d before the rebase, on Linux/KVM, Linux/MSHV, and Windows/WHP on those VMs, and a --x-time-abi-verify cold boot on each logs time ABI CPU checks passed with 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 two verify openhcl binary size jobs: they compare with the feature/microvm/dev CI run of c32c57d12, which was still running, and their rerun passed once it completed.

Notes

  • Every check passes and fails as before, and a failure keeps the code that it had: an error leads with the failure of the first check that fails. A restore whose record differs now also runs the check of VP 0's CPUID and the support check, as every boot does. Both only read, before any VP runs: VP 0's CPUID as the backend presents it, and the CPU surface that the backend supports.
  • Only the microVM profile's time ABI checks change.

@github-actions github-actions Bot added the Guide label Oct 29, 2026
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>
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the copilot/microvm-cpu-surface-every-difference branch from 93cf08c to e4c741e Compare October 29, 2026 21:31
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>
@github-actions

Copy link
Copy Markdown

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>
@github-actions

Copy link
Copy Markdown

@ppenna
Pedro Henrique Penna (ppenna) merged commit e4c741e into feature/microvm/dev Oct 30, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant