Repository navigation
Description
Parent: #1076. Phase: 3, NVX's own binaries on the new interface. Needs: #1077, #1082; inside phase 3, groups of #1083, #1084 (see the table below). Unblocks: inside phase 3, groups of #1083, #1084; #1086, #1087, #1089, #1090. The lanes of phase 3 meet at group level, never in a cycle: each group issue names the groups that it needs.
Goal. nvx-init boots a layered root as PID 1 (#817): new code lives under the hidden guest::init module, builds the space where it is, switches into it once, and runs each exec as a plain process. The managed agent stays in guest::managed_agent; its direct mode shares nvx-init's exec core, and layered roots and managed blockless VMs share its NVXC loop. nvx-init captures when the host asks, activates a restore, and becomes the init of the layered roots and capture VMs that the new launches start; the old CLI paths keep the old layered init until the CLI replaces them.
Today (dev e42b1795) and after:
| Area | Today | After |
|---|---|---|
| Layered init | The shell nvx-init-agent: one-shot roots run through the container helpers (nvx-container-launch and nvx-container-enter), and managed roots hand their executions to nvx-managed-agent. |
The nvx-init binary over hidden guest::init, always managed, for the layered roots and capture VMs of the new launches; sandbox run becomes a cold boot, one exec and a stop in #1111. The old paths stay until #1110 and #1111 replace them. |
| Executions | guest::{exec, spawn, process, cgroup, entry}, with a cgroup and namespaces per exec. |
A fork and exec in its own process group. The child resets oom_score_adj and nice, sets its credentials (no supplementary groups, empty capability sets, no_new_privs), changes to its working directory, and execs. No cgroups, no namespaces, no limits. |
| Priority | None. | PID 1 and its helpers run with oom_score_adj -1000 and nice -10. |
| Helpers | Two long-running processes, which the shell starts and nothing tracks: the time daemon, which nvx-time boot forks, and, when listeners are published, the announcer /sbin/nvx-ingress. |
The same two processes, registered with nvx-init. The shell /init starts them before the switch and hands their process IDs to nvx-init; after a restore, nvx-init starts /sbin/nvx-ingress itself, after apply and before its switch. The VM ends if a helper fails. nvx-init runs no other guest tool: the capture's repair reseeds in process, and nvx-init powers off itself. |
| Capture | The shell nvx-snapshot. |
NVXC's capture request: refuse while an execution runs or, when the request asks, kill the process groups and sweep every process but PID 1 and its helpers; then snapshot::capture; after MustEnd, power off with its status. |
| Restore | The shell nvx-snapshot resumes a captured guest; the layered init has no activation protocol. |
Attach again; accept the activate message; Activation; apply; the runtime mounts; the announcer when listeners are published; the switch; completion; Ready; then the mapping table and Start. |
Groups, in order. Each group issue lists its PRs, with their goals, contents, Needs and estimates.
| Group issue | Delivers | PRs | Needs |
|---|---|---|---|
| #1115 | nvx-init boots a layered root, and runs each exec as a plain process | SL7.5a, SL7.5b, SL7.5c, SL7.5d | #1091, #1104, #1105 |
| #1116 | The managed agent's direct mode runs on nvx-init's exec core | SL7.6a, SL7.6b | #1109, #1115 |
| #1117 | nvx-init captures and restores, and boots the new launches' layered roots | SL7.7a, SL7.7b, SL7.8a | #1105, #1113, #1115, #1116 |
Notes.
- The space stays where it is. nvx-init uses
guest::{root, view, gpt}, the mapper and theapplyfamily directly; nvx-rs slimming, phase 4.3: the code that only NVX's programs use, and the error codes, become private #1088 later makes them crate-private in place. - The shell
/initstays for early boot and blockless VMs: it runsnvx-time boot, configures the network, starts the helpers, and runs a blockless VM in the mode that the CLI's tokens name. It hands nvx-init each VM withnvx_sandbox=1and no OpenVMM lifecycle token; until nvx-rs slimming 4.2.3: the old configs, the old launch code andbundledare gone #1122, a layered root with that token still goes to the old layered init. - Helpers are processes, not the guest tools. nvx-init runs only
/sbin/nvx-ingress; the other guest programs serve the shell/init,nvx-snapshotand the tests, while nvx-init uses their library code in place. - The managed modes share one loop. Layered roots and managed blockless VMs share
guest::managed_agent'sdispatchandseam, keep its default environment andPWDrules, and take a cold boot's workload identity from the CLI's tokens; they use none ofguest::{exec, spawn, process, cgroup, entry}. The agent's sandbox mode keeps them until nvx-rs slimming 4.2.4: the exec engine, the process modules and the old layered init are gone #1123 deletes it. - The initramfs includes nvx-init, which takes the helpers' process IDs from the shell
/init. A layered root with OpenVMM's lifecycle token comes only from the old CLI path until nvx-rs slimming 3.1.5: the sandbox lifecycle runs on the new interface and nvx-init #1110 and nvx-rs slimming 3.1.6: a managedsandbox run, and one exec at a time #1111 replace it. - A named snapshot is captured before a layered root exists. The capture VM is blockless and waits in nvx-init for NVXC's capture request; a restored VM gets its image, upper and workload setup at activation.
- The old layered init is deleted in nvx-rs slimming, phase 4.2: the old code is deleted, consumers first #1087, with the managed agent's sandbox mode. Until the test adapter goes, the adapter overlays its own guest at
/sbin/nvx-init.
Tests. PID 1's signals, reaping, console, exit statuses, priority, and shutdown by sync and power-off; the registry of the two helpers, and the VM's end when one fails. A cold boot parses the root's and the view's tokens, nvx_maps and nvx_share, the RAM upper's cap included, then assembles the root, mounts the export, the shares and the runtime filesystems, applies the view and switches once. Each exec's pipes, signals, exit status, credentials, default environment and PWD, and the end of a process group. Layered and blockless managed roots share the NVXC loop, and the direct-mode agent no longer announces EXEC_CGROUP. A capture is refused while an execution runs; when the request asks, the executions' process groups are killed, then every other process but PID 1 and its helpers is swept; nothing is sent until capture returns. A restore runs in order, and keeps the applied space, the mapper, the source root, the helpers and the Activation. The initramfs contains nvx-init; a layered root with OpenVMM's lifecycle token still boots through the old layered init, and a capture VM reaches nvx-init's capture loop without a root.
Done when: every group issue is closed, and the layered roots and capture VMs that the new launches start boot through nvx-init.
Activity
nvxa library of mechanisms and value types #1076ppenna commentedon Nov 11, 2026
All three groups of this subphase are complete and closed: #1115 (nvx-init boots a layered root and runs plain-process execs), #1116 (SL7.6a #1310, SL7.6b #1421) and #1117 (SL7.7a #1431, SL7.7b #1447, SL7.8a #1453). Every PR has merged into
feature/nvx-refactor, whose post-merge CI run at394c89025epassed: https://github.com/microsoft/nvx/actions/runs/42952780739. Closing the subphase as complete.