What rust-vmm Is

rust-vmm is a community project, not a product. It ships a set of small Rust crates — each in its own GitHub repository under the rust-vmm organization — that several virtual machine monitors build on. There is no rust-vmm binary, no VMM you can boot, no release that bundles everything. There is kvm-ioctls, there is vm-memory, there is linux-loader, and a couple dozen siblings, each versioned and published to crates.io independently. Firecracker consumes a subset; Cloud Hypervisor consumes a larger subset; both pull from the same audited code. This chapter is the why and the how of that arrangement, and the one fact you most need as a contributor: a Firecracker change sometimes belongs upstream, in a rust-vmm crate, not in the Firecracker tree.

After this chapter you can: explain the philosophy that justifies the project; describe its per-repo + gatekeeper governance and the community repo; explain what rust-vmm-ci enforces; outline how a new crate gets added; and decide, for a given change, whether it lands in firecracker or upstream.

Note: This is the contributor-mindset companion to the crate chapters that follow. The crate chapters teach you the code; this chapter teaches you the project — and the boundary between "fix it here" and "fix it upstream" is a judgment call maintainers will expect you to make correctly.


The philosophy: write the dangerous code once

A VMM is a privileged host process whose whole job is to safely run untrusted guest code. The lowest layers of that job are also the most dangerous:

  • FFI to the KVM uapi — get a struct layout or an ioctl number wrong and you have undefined behavior in code that talks to the kernel.
  • Guest-memory access — every read and write must be bounds-checked against attacker-influenced addresses, or you have an out-of-bounds host access.
  • Virtqueue parsing — the descriptor table, available ring, and used ring are all in guest memory, fully attacker-controlled; a naive parser is an escape primitive.
  • Raw ioctl/mmap/eventfd plumbing — the unsafe glue every VMM needs.

Before rust-vmm, every Rust VMM re-implemented all of this. Firecracker had its own. crosvm had its own. Cloud Hypervisor (then "cloud-hypervisor") had its own. Three subtly different copies of the most security-critical code in the stack, each with its own bugs, each fuzzed (or not) independently. The rust-vmm thesis is blunt: don't re-implement low-level VMM code — share it, and audit it once. One vm-memory with one set of bounds checks, fuzzed continuously, used by everyone, is safer than three hand-rolled copies. The same argument that makes a minimal device model good for Firecracker's security makes a shared, audited foundation good for the whole ecosystem.

flowchart LR
    subgraph before["Before rust-vmm"]
        A1["Firecracker:\nown kvm/mem/loader"]
        A2["crosvm:\nown kvm/mem/loader"]
        A3["Cloud Hypervisor:\nown kvm/mem/loader"]
    end
    subgraph after["With rust-vmm"]
        B1["Firecracker"] --> S["one audited\nkvm-ioctls / vm-memory /\nlinux-loader / ..."]
        B2["Cloud Hypervisor"] --> S
        B3["others"] --> S
    end

This is not free. Sharing a crate means coordinating across companies with different priorities; it means a change you want has to be acceptable to Cloud Hypervisor too; it means slower iteration than editing your own tree. Firecracker deliberately keeps some things in-tree because of that cost — most visibly its virtio device implementations (see virtio-queue.md), where it wants tight control over the exact device behavior and attack surface. The in-tree-vs-upstream line is a real engineering trade-off, decided case by case.


Governance: per-repo maintainers, gatekeepers, the community repo

rust-vmm is decentralized by design. There is no single steering committee that owns all the code. The structure:

LayerWhat it isWhere to find it
Per-repo maintainersEach crate repo has its own listed maintainers who review and merge that crate's PRs.each repo's CODEOWNERS / README / MAINTAINERS
GatekeepersA small org-wide group with admin rights, handling cross-cutting decisions, new repos, releases, security.the rust-vmm/community repo
The community repoThe org's "constitution": meeting notes, the new-crate proposal process, membership rules, the code of conduct, the CI submodule.github.com/rust-vmm/community
# Read the governance directly — it is short and authoritative:
#   github.com/rust-vmm/community  → README, MAINTAINERS, meeting notes
# For any single crate, the maintainers are in its own repo, e.g.:
#   github.com/rust-vmm/kvm-ioctls → CODEOWNERS / README

Contribution is by GitHub PR, no CLA, with sign-off discipline and the usual expectation that each commit is buildable, tested, and clippy-clean. Because each crate is independent, the people who review your vm-superio change are not necessarily the people who review your kvm-ioctls change — and several of them are also Firecracker maintainers wearing the other hat. That overlap is why "upstream first" is a credible path: the same AWS engineers maintain parts of both.

Tip: Firecracker's own MAINTAINERS.md and the rust-vmm crate CODEOWNERS overlap. When you propose an upstream change, you are often talking to people who already know Firecracker's needs — frame the change in terms of all consumers (Cloud Hypervisor included), not just Firecracker.


rust-vmm-ci: one bar for every crate

The thing that keeps a federation of independent crates at a uniform quality is rust-vmm-ci — a shared CI configuration distributed as a git submodule that each crate repo pulls into itself. Instead of every crate inventing its own pipeline, they all run the same checks:

CheckWhat it enforces
cargo build (multi-target)builds on x86_64 and aarch64, stable + MSRV
cargo testunit + integration tests, sometimes under multiple feature sets
cargo clippy -- -D warningslints are errors, exactly like Firecracker
cargo fmt --checkformatting is enforced, not suggested
coveragea per-crate coverage floor that a PR may not lower
fuzzing (where applicable)continuous fuzzing of the parsers (e.g. virtio-queue)
commit/style checkssign-off, commit message hygiene
# In any rust-vmm crate checkout you'll see the submodule:
git submodule status            # lists rust-vmm-ci
ls rust-vmm-ci/                  # the shared pipeline definitions

If you have internalized Firecracker's tools/devtool checkstyle / checkbuild --all / warnings-as-errors clippy gate (see Lab 2.2), rust-vmm-ci will feel familiar — it is the same discipline, applied across the ecosystem. A change that passes Firecracker's bar is most of the way to passing rust-vmm-ci.


How a crate gets added

New crates don't appear by accident. The community repo documents the process, which in practice looks like:

  1. Propose a new crate in the community repo (an issue / meeting agenda item): what problem it solves, why it belongs shared, who will maintain it.
  2. Discuss in the regular community meeting — is the scope right, does it overlap an existing crate, is there more than one willing consumer?
  3. Bootstrap the repo with rust-vmm-ci, an initial maintainer set, and the standard license (Apache-2.0, often dual with BSD/MIT).
  4. Publish to crates.io once it stabilizes.

Three of the crates you will read about took a shortcut through this process: they were donated from Firecracker. seccompiler, event-manager, and vm-superio were extracted out of the Firecracker tree, generalized so they were not Firecracker-specific, and contributed upstream so the whole ecosystem could share them. That is the highest-leverage move available to a Firecracker contributor — not just fixing the foundation, but enlarging it.


The monorepo consolidation

For most of its history rust-vmm was strictly one crate per repository — dozens of small repos. That has costs: cross-crate changes need coordinated PRs across repos, dependency bumps ripple slowly, and the submodule-per-repo CI is heavy. The project has been consolidating related crates into shared repositories (for example, grouping the virtio crates together) to make cross-cutting work tractable, while still publishing each crate independently to crates.io. The direction — fewer repos, same independent crates — is what to remember; the exact current grouping is something to check on the org page, because it moves.

Note: Because repo boundaries are shifting, never assume "crate X lives in repo X." Find the source from your dependency, not from memory:

# From the FC checkout, jump straight to a dependency's source:
cargo doc -p vm-superio --no-deps --open      # docs for the pinned version
# Or find where cargo unpacked it:
find ~/.cargo/registry/src -maxdepth 1 -type d -name 'vm-superio-*'

Why this matters to a Firecracker contributor

Here is the practical payoff, and the reason this chapter exists at all. When you triage a Firecracker issue or design a fix, you must answer a routing question that a less experienced contributor gets wrong: whose code is this?

Symptom / changeLikely homeWhy
Serial console drops a byte under loadvm-superio (upstream) or FC's use of itthe UART model is the shared Serial
KVM_RUN exit not handled / a new VcpuExit variant neededkvm-ioctls (upstream)the exit enum is defined there
Guest-memory bounds check too strict/loosevm-memory (upstream)the GuestMemory impl owns bounds
Kernel fails to load a valid vmlinuxlinux-loader (upstream)the ELF parser is the shared loader
A seccomp JSON operator behaves wrongseccompiler (upstream-origin)the compiler is shared
FC's virtio-block request handlingfirecracker (in-tree)FC keeps its own virtio devices
FC's API server validationfirecracker (in-tree)wholly FC-specific
FC's snapshot formatfirecracker (in-tree)FC-specific persistence

Get this wrong and your PR goes to the wrong repo, the wrong reviewers, and the wrong test suite. Get it right and you become the kind of contributor who fixes the foundation — a fix that ships to Cloud Hypervisor too, then flows back into Firecracker on the next version bump. The mechanics of doing that — forking a rust-vmm repo, the PR, the version-bump-then-consume cycle — are Lab R4.

There is a second-order skill here too: dependency bumps. Periodically Firecracker raises its pinned rust-vmm versions. Someone has to do that PR — bump the Cargo.toml, regenerate Cargo.lock, fix whatever API breaks, re-run the pytest suite. It is recurring, high-visibility, trust-building work, exactly like "upgrade the bundled Lucene" is in OpenSearch. Find the history:

# Past rust-vmm version-bump PRs are a model for your own:
gh search prs --repo firecracker-microvm/firecracker "Update kvm-ioctls OR Update vm-memory OR bump rust-vmm" --limit 20
git log --oneline -- Cargo.lock | head -20

Validation: prove you understand this

  1. State the rust-vmm thesis in one sentence, and connect it to the same security argument that justifies Firecracker's minimal device model.
  2. Describe the governance: per-repo maintainers, gatekeepers, and the role of the community repo. Where do you read the actual rules?
  3. What does rust-vmm-ci enforce, and how is it distributed to each crate? Name three checks it shares with Firecracker's devtool.
  4. Name the three crates Firecracker donated upstream, and explain why donating a crate is higher-leverage than fixing one.
  5. Given a bug where the serial console drops bytes, and another where the API server mis-validates a drive, say which repo each fix belongs in and why.
  6. Explain what a "rust-vmm version bump" PR in Firecracker involves and why it is trust-building work.

Next: kvm-ioctls and kvm-bindings — the safe RAII wrappers and the raw uapi FFI that put Firecracker in touch with KVM.