Repository navigation
nvx-rs: serve clones of each processor count from one template - #926
Open
Enrique Saurez (esaurez) wants to merge 2 commits into
Open
Enrique Saurez (esaurez) wants to merge 2 commits into
Enrique Saurez (esaurez) wants to merge 2 commits into
Conversation
Enrique Saurez (esaurez)
force-pushed
the
esaurez/849-cpu-targets-20261026
branch
from
October 27, 2026 05:03
66ccf0e to
8f64084
Compare
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
CPU activation and deferred time checks still need the pending Linux and cross-backend VM validation on the final integration base, followed by human review.
1 open issue
What changed in this PR
Implements per-clone CPU targets for #849, allowing one NVX template to serve supported processor counts from its boot-online count to its capacity.
Changes:
- Adds boot-online CPU configuration, clone target validation, and restore arguments.
- Extends guest repair to activate CPUs and report them for deferred time checks.
- Updates runtime-adapter options, probes, tests, and documentation.
| File | Description |
|---|---|
| tests/runtime-adapter/tests/vm_template.rs | Tests boot-online counts and capture limits. |
| tests/runtime-adapter/tests/vm_clone.rs | Tests multiple CPU targets from one generation. |
| tests/runtime-adapter/tests/template_operations.rs | Tests invalid boot-processor input. |
| tests/runtime-adapter/tests/template_capture.rs | Checks CPU counts in capture classes. |
| tests/runtime-adapter/tests/clone_start.rs | Tests processor options and request propagation. |
| tests/runtime-adapter/src/worker/probes.rs | Adds CPU-state and restored-CPU probes. |
| tests/runtime-adapter/src/template.rs | Updates allowlist documentation and tests. |
| tests/runtime-adapter/src/clone.rs | Carries clone processor targets. |
| tests/runtime-adapter/src/capture.rs | Adds boot-processor configuration and defaults. |
| tests/runtime-adapter/src/bin/runtime-adapter-host.rs | Parses CPU options and selects clone defaults. |
| tests/runtime-adapter/scenarios.txt | Registers three new VM scenarios. |
| tests/runtime-adapter/README.md | Documents CPU options, repair, and scenarios. |
| nvx-rs/tests/vectors/README.md | Updates the documented OpenVMM source revision. |
| nvx-rs/tests/vectors/openvmm/platform_command_line_token_is_invariant.rs | Adds maxcpus= to the copied allowlist. |
| nvx-rs/src/testing/fake_openvmm.rs | Validates canonical capture CPU limits. |
| nvx-rs/src/protocol/status.rs | Clarifies processor-repair status descriptions. |
| nvx-rs/src/host/template/store/capture/tests.rs | Tests capture with CPUs offline at boot. |
| nvx-rs/src/host/template/store/capture.rs | Allows and propagates boot-online CPU counts. |
| nvx-rs/src/host/template/plan/tests.rs | Tests CPU combinations, rendering, and refusals. |
| nvx-rs/src/host/template/plan.rs | Validates boot counts and renders maxcpus=. |
| nvx-rs/src/host/template/clone/tests/launch.rs | Tests processor-target restore arguments. |
| nvx-rs/src/host/template/clone/tests.rs | Tests target bounds and activation resources. |
| nvx-rs/src/host/template/clone/record.rs | Records the requested CPU count. |
| nvx-rs/src/host/template/clone/launch.rs | Conditionally passes --restore-processors. |
| nvx-rs/src/host/template/clone.rs | Validates and retains clone CPU targets. |
| nvx-rs/src/guest/clone/repair/tests.rs | Tests CPU activation, retries, and failures. |
| nvx-rs/src/guest/clone/repair.rs | Activates CPUs and reports newly online CPUs. |
| nvx-rs/src/guest/clone.rs | Documents processor repair and time checks. |
| nvx-rs/README.md | Updates host and guest API descriptions. |
Review effort: Balanced
Enrique Saurez (esaurez)
force-pushed
the
esaurez/849-cpu-targets-20261026
branch
from
October 27, 2026 05:20
8f64084 to
0c515f7
Compare
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
CPU restore spans host, guest, and OpenVMM contracts, with Linux gates, cross-backend VM validation, and final review after the integration rebase still pending.
No open issues 🎉
1 resolved since last review
Review effort: Balanced
Enrique Saurez (esaurez)
changed the base branch from
esaurez/847-pr2-start-run-suite-20261024
to
esaurez/849-base-snapshot-20261028
October 28, 2026 17:31
Enrique Saurez (esaurez)
marked this pull request as ready for review
October 28, 2026 17:31
This was referenced Oct 28, 2026
Enrique Saurez (esaurez)
force-pushed
the
esaurez/849-cpu-targets-20261026
branch
from
October 29, 2026 09:38
0c515f7 to
2dd7ce6
Compare
Enrique Saurez (esaurez)
changed the base branch from
esaurez/849-base-snapshot-20261028
to
esaurez/848-shorter-images-absent-scratch-20261026
October 29, 2026 09:38
Enrique Saurez (esaurez)
force-pushed
the
esaurez/848-shorter-images-absent-scratch-20261026
branch
from
October 29, 2026 15:39
1c77b97 to
ce7932d
Compare
A template may now boot with some of its processors offline, which OpenVMM records, and a restore with a processor target of more of them asks the clone's guest to bring the target's prefix of CPUs online. The repair refused any target that the online CPUs did not meet already. The repair's processor stage now reads the online CPUs, which must be a prefix, and refuses a target below them, since it takes no CPU offline. It brings each offline CPU of the target's prefix online through sysfs, as nvx-snapshot does, and verifies that the online CPUs are exactly that prefix, else it fails with the new cause RepairCause::Activation. These CPUs were in the VM since its boot, so no device is plugged. Its first attempt records the CPUs that the clone captured online, so a retry brings online only the CPUs that are still offline. The finish hands the CPUs beyond those to the time ABI's restore record as new_cpus, so the time daemon's restore checks cover them too. The stage's description is now "activate the processor target", and the status 41 and the module's documentation say what the stage does. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4582f45d-8921-477b-8006-e9c7c709af88
One template now serves every supported processor count N, from the count B that its VM boots with online up to its capacity C, so that a template class needs no capture per processor count. nvx-rs: TemplateResources gains boot_processors, 1, 2, 4, or 8, at most the processors. A template with fewer online at boot boots with "nvx_sandbox=1 maxcpus=B", the canonical token of OpenVMM's platform allowlist, which OpenVMM records as the snapshot's processors online at boot and the key keeps. The store no longer refuses such a class. A template whose processors are all online at boot renders no maxcpus= and records none, as before. CloneRequest gains the processor target, processors. ClonePlan checks it against the key before any VMM starts, with the memory target: it must be 1, 2, 4, or 8, from the template's processors online at boot, or its capacity when it records none, to its capacity, else the plan fails with Evidence::InvalidTargets. The activation record expects the target's CPUs. A restore passes --restore-processors N exactly when the key records processors online at boot, so a template whose processors are all online at boot restores as before. The fake OpenVMM's capture admits maxcpus= as OpenVMM does. runtime-adapter: create and refresh take --boot-processors B, 1 by default, the fewest that the template's clones take. start and run take --processors N, the template's processors online at boot by default. The worker's new probe, processors, reports the online, present, and possible CPUs, and the CPUs that the restore brought online, from the time ABI's record. Three new VM scenarios: - vm_template a_template_whose_processors_are_all_online_at_boot_limits_none captures a template without maxcpus=. - vm_clone one_generation_serves_clones_of_each_processor_count_from_its_boot_online_count_to_its_capacity restores one generation of 4 processors, 1 online at boot, at 1, 2, and 4 CPUs, and the plan refuses targets of 3 and 8. - vm_clone a_generation_refuses_clones_of_fewer_processors_than_its_template_booted_with shows that a template that boots with 2 refuses a target of 1. The README describes the options, the checks, and the scenarios. Part of #849. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4582f45d-8921-477b-8006-e9c7c709af88
Enrique Saurez (esaurez)
force-pushed
the
esaurez/849-cpu-targets-20261026
branch
from
October 29, 2026 15:45
2dd7ce6 to
02b92e2
Compare
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.

Part of #849. Stacked on #925.
Chain: #951 → #954 → #957 → #959 → #960 → #955 → #958 → #962 → #963 → #925 → this PR, on
dev; #879, #881, #885, #886, #877, #932, #884, #887, #933, #880, #936, #937, #939, #940, #941, #888, #949, and #950 have merged.What and why
Until now, a template booted with all of its processors online (B = C), and its clones got no processor target, so each processor count needed a template of its own. OpenVMM can bring a contiguous prefix of a snapshot's processors online at restore: a capture with
maxcpus=Brecords B as the boot-online count, and--restore-processors Nrestores with N online, where B <= N <= C. With this PR, one template serves each supported count from its B to its capacity C.Host:
nvx::host::templateTemplateResources::boot_processorsis B: 1, 2, 4, or 8, and at most the processors C.TemplatePlan::newrefuses any other value before a VM starts.nvx_sandbox=1 maxcpus=B. That is the canonical token that OpenVMM's platform tier admits and records as the snapshot's boot-online count, and the key keeps it (TemplateKey::boot_processors).maxcpus=and records none, as before. The store's interim refusal of B < C is gone.CloneRequest::processorsis the clone's processor target N.ClonePlan::newchecks it against the key, together with the memory target, before any VMM starts. N must be 1, 2, 4, or 8, from B (C for a template that records none) up to C. Otherwise the plan fails at the request, with the evidenceinvalid-targets.--restore-processors Nonly when the key records B. A template that records none restores at C, as before.maxcpus=Bas OpenVMM does.Guest:
nvx::guest::clone::repairThe repair's processor stage now activates the processor target, while host input is still gated and before the acknowledgement:
/sys/devices/system/cpu/cpuK/online, asnvx-snapshotdoes.0..N-1. Otherwise it fails with the new causeRepairCause::Activationand status 41,REPAIR_PROCESSORS.These CPUs have been in the VM since its boot, so no device is plugged. A retry brings online only the CPUs that are still offline. The finish reports CPUs B to N-1 through
RestoreFinish::new_cpus, so the time daemon's deferred restore checks cover them too.Authentication timer
No change. The host keeps connecting after the restore-ready event.
Runtime adapter
createandrefreshtake--boot-processors B, 1 by default. That is the fewest processors the template's clones take, so by default one template serves every count up to its--processorscapacity. B belongs to the class and the key.startandruntake--processors N. The default is the template's B, or C when the template records none. Without N or a memory target, the command reads the generation's key once, before the lease, as it does for the memory target; a key that cannot be read leaves both to NVX's plan, which attributes the failure.processorsprobe. It reports the online, present, and possible CPUs, and the CPUs that the restore brought online, read from the time ABI's record/run/nvx/time-restore.Tests
nvx-rs unit tests:
plan: every template of every B up to C.templates_limit_their_processors_online_at_boot_on_their_command_linerendersmaxcpus=Bonly when B < C. The refusals now cover B of 0, 3, and 16, and B above C.store::capture:captures_limit_the_processors_that_their_class_keeps_offline_at_bootcaptures 4 processors with 1 online at boot, which gives--cmdline "nvx_sandbox=1 maxcpus=1"and a key of (4, 1). It replaces the interim rule.clone:processor_targets_are_counts_from_the_templates_processors_online_at_boot_to_its_capacity. A template of 8 with 2 online at boot serves 2, 4, and 8, and refuses 0, 1, 3, 6, 16, andu32::MAXwithInvalidTargets. A template that records none refuses 1 and 4, and serves only its capacity, 2.clone::launch:a_clone_of_a_template_with_processors_offline_at_boot_restores_its_processor_targetrestores a clone in RAM with--restore-processors, beside the--restore-absent-scratchof its devices. The exact arguments of the existing restore test still hold no such option for a template that records none.fake_openvmm: the capture admits a canonicalmaxcpus=Bof at most--processors, and refusesmaxcpus=01,maxcpus=3, a B above the processors, and a second token.guest::clone::repair, with four new tests:Runtime adapter, host-only:
clone_startpasses the processor target into NVX's request, and refuses--processors 0and--boot-processorsonstart.template_capturechecks the class's (C, B): (1, 1) by default, then (4, 1) and (4, 2), each with a class of its own.template_operationsrefuses--boot-processors one.Runtime adapter VM scenarios (
scenarios.txt, now 158):vm_templatea_template_whose_processors_are_all_online_at_boot_limits_none: 2 of 2 online at boot, nomaxcpus=, and a key that records none.vm_templatea_template_without_a_network_has_no_nicnow captures 2 processors with 1 online at boot. The capture assertions checkmaxcpus=Bexactly when B < C, and the key's B, in every capture scenario.vm_templatea_class_that_no_capture_takes_is_refused_before_the_storealso refuses 2 processors with 4 online at boot.vm_cloneone_generation_serves_clones_of_each_processor_count_from_its_boot_online_count_to_its_capacity: one generation of 4 processors, 1 online at boot.0,0-1, and0-3, new CPUs none,1, and1-3, and possible CPUs0-3.invalid-targetsand no VM.vm_clonea_generation_refuses_clones_of_fewer_processors_than_its_template_booted_with: a template of 4 with 2 online at boot.0-1online and no new CPUs; at 4 it restores with0-3online and new CPUs2-3.Guide changes (#591's numbering)
These changes are not made in #591; they are listed here for it:
maxcpus=Btoken, with B in {1, 2, 4, 8} and at most the processor capacity C. A template's capture adds it only when B < C, and OpenVMM records it as the snapshot's boot-online count. A template whose processors are all online at boot carries nomaxcpus=and records no boot-online count.--restore-processors Nonly for a snapshot that records B, and the clone's activation record expects N online processors.0..N-1through/sys/devices/system/cpu/cpuK/online, then rereads the list and requires exactly0..N-1. The finish reports CPUsB..N-1as new CPUs, and the conformance checks that rerun after the acknowledgement (step 7) cover them. The guest library reports a failure as status 41.Validation
At this PR's head 02b92e2, the same two commits as the earlier head 2dd7ce6, restacked onto #925's head ce7932d: its tree, 4d6e9339, is the merge of 2dd7ce6 into
devat fbeb563, which holds #951, #954 and #957, plus #955's fix that treats a path whose links loop as a changed object. That merge, without the fix, passed the documentation gates ofnvx-rsand of the test adapter, Clippy, validate-nvx on Linux and on Windows, and the Markdown link check; the fix has its own tests in #955. The rest of this section describes 2dd7ce6, on #925's earlier head 1c77b97.At 2dd7ce6 (tree 16977fde), on #925 1c77b97:
--lib, and--lib --no-default-features;-D warnings;NVX CLI / Windowsjob.test-runtime-adapter --check-only, which names 158 scenarios.guest::clone,guest::root, andguest::mappingstests (13), as root.v0.1.0-dev.2d14547b669f, and the initramfs and guest agent built from this head.vm_clone33,vm_layered43,vm_template13,vm_restart3,vm_steps3, and the start and run scenarios.vm_clonea_clone_refuses_a_scratch_image_whose_upper_an_earlier_clone_used.vm_clone.