Skip to content

nvx-rs: expose the guest runtime as a library #619

Description

Parent: #535. Phase: A1, in parallel with A1-host; implementation PRs open directly. Behavior: unchanged, except that port access is scoped to each transaction.

Goal. Expose seven API families, and the guest role of a shared NVXS session, that any guest init or agent can call without NVXC framing and without NVX's PID 1. NVX's own managed agent is one such caller.

Today (dev ff95973):

  • The nine guest program modules export only main().
  • exec::run takes the NVXC session and a decoded GuestExecPayload, and enforces the 1 MiB output budget.
  • Launch takes AgentConfig, depends on the managed helper descriptors and on setpriv, and fixes stdin to the null device.
  • Cleanup reaps with waitpid(-1), and settles the whole cgroup only in direct mode.
  • Mapping apply has two implicit roots: the export root and absolute guest targets.
  • Time runs only as commands and keeps port permission for the whole command. Reseed uses the random device.
  • The guest's NVXS handling is tied to NVXC decoding inside the managed agent.

Scope. These become public under the guest feature:

  1. Exec: one execution object per workload.
    • It accepts cancellation, a timeout or a disconnection, and the exit status that the caller observes.
    • It emits launch, output and terminal events.
    • I/O is bounded and backpressure-aware. Neither NVXC nor an async runtime is required.
    • It has an explicit flow-control seam, which A5's credit engine extends rather than replaces.
  2. Spawn: a neutral argv and environment, an explicit root with a separate working directory, caller-supplied stdio, an optional execution cgroup, and prepared launch-stage inputs. Descriptor handoffs are ownership-safe. No managed helper or identity policy is required.
  3. Reaping: exactly one status collector, owned by the caller. No library function waits for arbitrary children.
  4. Mappings: decoded entries with explicit export and target roots. They stay path-based here, and A3 roots them at descriptors. Batching and NVXC sequencing stay in the adapter.
  5. Cgroups: explicit agent and workload paths, and per-execution handles to prepare, place, check occupancy, kill and settle. Callers choose the resource values and the settlement mode.
  6. Time and reseed: typed inputs, results and errors for capture, restore_finish and reseed, with no output parsing. For each transaction:
    • port permission is taken on one thread;
    • a partial grant is rolled back;
    • revocation is verified before any spawn.
  7. Cold boot: a synchronous time-step call, separate from daemon creation. The daemon stays a separately supervised process.
  8. NVXS session, guest role: validated records, incremental parsing and the guest's session state, with no NVXC dependency. Records are pure state; I/O stays a thin driver. NVX's managed agent and the test adapter both use it.

The adapter keeps the NVXC framing, the stdin policy, the 1 MiB cap, admission, identity selection and mode-specific cleanup. AgentConfig, wire payloads and internal syscall modules stay private.

Not in scope: root assembly and PID 1 (A3), descriptor-rooted mappings (A3), protocol v2 (A5), hotplug, and large-content hashing.

Acceptance:

  • NVX's managed agent and guest tools become thin callers. Existing observable fixtures pass unchanged on KVM, MSHV and WHP, and Test the managed agent's direct-mode launch without privileges #601's direct-launch cases are completed.
  • The in-repo test adapter exercises all seven families and the NVXS session through public APIs only, with its own framing. It lives at tests/runtime-adapter/, with its own lockfile and default features off, and is wired into check-nvx-rs and the microVM workflow.
  • CI change classification includes tests/runtime-adapter/, with a classifier test showing that an adapter-only change runs the microVM jobs.
  • Consumer-contract scenarios C0 (independent build) and the guest parts of C1 (NVXS) and C2 (concurrency) pass.
  • Tests cover:
    • an unrelated child's status is preserved;
    • descendants that hold pipes;
    • concurrent executions;
    • a stalled sink;
    • cancellation;
    • stdin EOF;
    • output-cap parity;
    • failures to grant or revoke port access;
    • a workload's port access failing inside a VM.
  • Static guest builds. Stripped binary and initramfs sizes are recorded before and after.

PR stack:

  1. G1: neutral spawn and descriptors, with Test the managed agent's direct-mode launch without privileges #601's seams. It builds on nvx-rs: build the plain spawn descriptors from the managed ones #611 (merged), which changed guest/sys/spawn.rs.
  2. G2: cgroups and status ownership.
  3. G3: the exec driver and the NVXC adapter.
  4. G4 (explicit roots) and G5 (time and reseed) run in parallel once the interfaces agree.
  5. G6: the NVXS session's guest role, and the test adapter's guest half.

Carries over:


Meta A: #535. Phases: A1-guest #619, A1-host #620, A3 #621, A4 #622, A5 #623, A6 #624.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions