State

Snapshot format and restore

A running VM captured whole at a safe point and restored mid-program, from a full image or a diff against a base.

A FlashVMM snapshot is a complete capture of a running FlashVM taken at a safe point (vCPU registers, interrupt controller and clock state, guest RAM, virtio device state and the disk overlay) in a sectioned, BLAKE3-digested file that restores the program mid-flight, either as a full image or as a diff against a base, from local disk or demand-paged through userfaultfd from a signed URL.

Restore is not a separate verb: it is the create call, PUT /v1/flashvm, with a snapshot or snapshot_url source. A snapshot carries device state and never the devices, so a restore names the bundle (kernel and root filesystem) it was captured against. A restored program resumes in 7.8 ms, and the same file underlies fork and checkpoints, sleep and live migration.

Key facts

Runs onLinux (KVM) · macOS (Hypervisor.framework) · Windows (WHP); remote restore from a URL on Linux and macOS
InterfacesCLI flash snapshot, restore, clone, snapshots, source · MCP flash_cli, flash_api, flash_resource · REST /v1/flashvm/snapshots, /v1/flashvm/source
Restore time7.8 ms (Linux ARM, cloud bare metal), 17 ms (Linux x86, cloud bare metal)
SectionsVM state, vCPUs, RAM or RAM diff, devices, disk overlay, serial, virtio-mem region; each length-prefixed and digested in a header table
RAM digestsBLAKE3 per 256 KiB chunk
Diff unit4 KiB page
CPU templateRequired to capture; host-raw or a named template

How it works

Capture

POST /v1/flashvm/snapshots freezes the guest at a safe point and writes every section, then answers 202 with an operation to poll. The VM must have been started with --cpu-template, so the CPU features the guest saw are recorded and checked at restore. The file records the guest TSC frequency, so a restore on a host with a different TSC rate programs hardware TSC scaling. It also records a mark of the bundle's kernel and root filesystem, taken from the files' names and contents.

Full and diff images

A full image holds the whole RAM section. A diff holds only the pages dirtied since its base, from KVM's dirty log plus the VMM's own writes (see memory). A VM restored with --diff-base captures diffs against that base from then on, and a rebase writes one capture self-contained and makes it the new base, so a large change is paid once.

Restore and verification

Before allocating anything, a restore runs its prechecks in a fixed order and refuses with a named reason: identity (the snapshot belongs to a different VM), cpu-vendor, mem-shape, vcpu-bound, template-unknown, bundle-mismatch and disk-shape. On Linux, guest RAM is then demand-paged through userfaultfd: the fd is registered before anything touches guest memory, and each fault is served with a chunk-aligned UFFDIO_COPY after the chunk's BLAKE3 digest is checked against the header table, in the instant before it becomes guest memory. A restore that could arm no verification is refused as ram-unverified. Every restored guest is reseeded with host entropy (see platforms).

Restore, clone and move

The identity of a VM is its socket name, so flash restore under the same --id brings that VM back. flash clone sends the same create with allow_identity_mismatch: true: a new VM whose RAM is mapped copy-on-write from the file, with MAC addresses derived from its own NIC addresses. Moving a VM between hosts is capture, transfer and restore; the bundle mark depends only on file contents, so the same bundle restores on any host.

Remote restore

flash restore --from-url URL --total BYTES restores from a ranged HTTP object. total comes from the object listing and bounds every fetch, so the server never decides how many bytes are real. On Linux the pager fetches 256 KiB chunks on fault through a 512-chunk (128 MiB) cache; on macOS the hvf engine reads the object in 4 MiB ranges. flash source resign swaps in a freshly signed URL while the guest runs.

Interfaces

CLI

flash snapshot svc --path /var/snap/svc.snap
flash snapshots svc ls
flash stop svc
flash restore --from /var/snap/svc.snap --bundle ./bundle --id svc --vcpus 2 --mem-mib 1024 --cpu-template host-raw --detach
flash clone --from /var/snap/svc.snap --bundle ./bundle --id svc-copy --vcpus 2 --mem-mib 1024 --cpu-template host-raw --detach
flash restore --from-url 'https://objects.example/svc.snap?sig=...' --total 1073741824 --bundle ./bundle --id svc2 --vcpus 2 --mem-mib 1024 --cpu-template host-raw --detach
flash source resign svc2 --url 'https://objects.example/svc.snap?sig=...' --total 1073741824

MCP

flash_api(vm_id: "svc", method: "POST", path: "/v1/flashvm/snapshots", body: {"path": "/var/snap/svc.snap"})
flash_resource(vm_id: "svc", resource: "snapshots")
flash_cli(args: ["restore", "--from", "/var/snap/svc.snap", "--bundle", "./bundle", "--id", "svc", "--vcpus", "2", "--mem-mib", "1024", "--cpu-template", "host-raw", "--detach"])
flash_resource(vm_id: "svc2", resource: "source")

REST

POST  /v1/flashvm/snapshots   {"path": "/var/snap/svc.snap"}   → 202 {"operation": "..."}
GET   /v1/flashvm/operations/{operation_id}
PUT   /v1/flashvm             {"source": {"type": "snapshot", "path": "/var/snap/svc.snap"}, "bundle_dir": "./bundle", "vcpus": 2, "mem_mib": 1024, "cpu_template": "host-raw"}
PUT   /v1/flashvm             {"source": {"type": "snapshot_url", "url": "...", "total": 1073741824}, "bundle_dir": "./bundle", ...}
PATCH /v1/flashvm/source      {"type": "snapshot_url", "url": "...", "total": 1073741824}   → 204

Contract: allow_bundle_mismatch: true waives bundle-mismatch and nothing else; allow_identity_mismatch: true waives identity to build a clone. PATCH /v1/flashvm/source returns 409 no_remote_source on a VM not restored from a URL and 422 digest_mismatch when the new URL names a different object; the new header is compared field by field (identity, size, mem_mib, RAM offset, per-chunk digests) before a single fault is re-pointed. A snapshot whose guest uses a secret proxy needs its key again at restore, or returns 422 secret_proxy_missing.

Guarantees

  • Mid-program restore. Registers, devices, RAM and disk come back together, so running processes continue.
  • Verified bytes. Each RAM chunk is checked against its BLAKE3 digest before the guest can read it.
  • One VM, one live copy. A snapshot is a move by default; a copy is an explicit clone with its own identity.
  • Checked compatibility. CPU template, memory shape, disk shape and bundle are confirmed before anything is allocated.

What it does

Related