Skip to content

feat(snapshot): add VM checkpoint lifecycle - #3

Merged
ltstriker merged 24 commits into
boxlite-ai:x_featuresfrom
lfld287:lfld287/memory-snapshot
Oct 28, 2026
Merged

ltstriker merged 24 commits into
boxlite-ai:x_featuresfrom
lfld287:lfld287/memory-snapshot

Conversation

@lfld287

@lfld287 lfld287 commented Oct 26, 2026 •

Copy link
Copy Markdown

TL;DR

Add Linux x86_64/KVM checkpoints preserving RAM, CPU, devices and shared files.

Design doc: boxlite-ai/boxlite#2111

Documentation: checkpoint contract

Size exception: special testing.

How it works

krun_snapshot_* freezes vCPUs and device workers, exports a self-contained image, imports paused state, then resumes devices before vCPUs. IRQ routing and CPUID handling match the restored guest while retaining compatibility checks.

Verification

The three IRQ/CPUID regression tests pass via make snapshot-test. Production-reverted runs fail at their defect checks. Integrated KVM continuation, DAX and rootless-seccomp tests pass on BoxLite #2112 at c855d75c.

Old TCP sessions are not migrated. Cross-host/AMD coverage remains unverified.

lfld287 and others added 12 commits October 22, 2026 19:24
Preserve the final guest RAM layout in a versioned file and restore owned mappings into a fresh KVM VM. Require confirmed vCPU pauses, reject unsupported writers, and resume all CPUs before publishing a valid snapshot.

Validation: scoped rustfmt and whitespace checks passed. Build and runtime tests were not run; CPU and device restoration remain out of scope.
Preserve CPU, kernel interrupt and timer state alongside RAM so the minimal VM can continue after source destruction. Validate target compatibility and restore on paused owning threads before explicit resume.
Freeze block workers at request boundaries and capture standalone disk
segments with CPU, KVM and RAM state in KRUNVM v2 images.

Restore devices paused with owned disk imports and explicit resume.
Preserve device-free v1 images and existing guest cache semantics.

Add regression sources and document the internal-only contract.
Builds, formatting, tests and KVM execution were not run as requested.
Preserve virtio device and queue state in KRUNVM v3 while dropping
old frames and sessions on import. Freeze all devices at one RAM cut,
reconnect the network backend, and complete pending TX as dropped.
Unify full checkpoints on KRUNVM v4 with explicit restore resources.
Freeze event-driven devices at callback boundaries, preserve legacy state,
and stop all owned vCPUs on guest reset or exit.

Incremental Linux checks and focused non-KVM tests passed. KVM reset and
restore execution remain unverified because this host lacks /dev/kvm.
Separate pause, export, import and resume so checkpoints leave both
source and restored VMs paused and exports can be retried safely.

Rebuild ordinary Unix IPC vsock connections after transport reset,
preserving queue and interrupt state in full snapshot format v5.
Reject TSI and require fresh host socket resources on import.

Validation: snapshot format, check and build targets pass; native vsock
16/16 and net 20/20 tests pass. Linux device tests pass 57/57 and
37 non-KVM VMM tests pass. KVM restore and real guest-agent reconnection
remain unverified because /dev/kvm is unavailable.
Preserve multiport queues, handshake state and partial TX progress
across the internal VM pause/export/import/resume lifecycle.

Use KRUNVM v6 and validate fresh console endpoints before restore.
Document local validation and the remaining KVM execution gap.
Freeze fs workers at completed request boundaries and restore FUSE sessions,
stable directory streams, handles and inode projections without a new INIT.
Cover the backend and review fixes with Linux snapshot tests.

Record the user-requested pause and remaining archive, DAX and owner work.
Full VM images remain v6; complete virtio-fs snapshots are not implemented yet.
Snapshot-mode shares record each DAX setup and removal after the host
mapping succeeds, so a checkpoint can describe the window as file
mappings, private anonymous memory and holes, keep objects only mappings
reference, and save the nonzero anonymous pages. Restore validates the
state and pages before mapping the whole window into the new device.

A host mmap or mprotect failure leaves the window layout unknown, so the
share fails closed: later mapping requests, freeze and capture are refused
(DaxLost) without touching window memory instead of trying a rollback.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A full VM snapshot with virtio-fs must restore without the source share
directories. Capture every share's whole tree (looked up or not) through
each share's own descriptors, dedup objects across shares, keep orphan
objects only sessions hold, and record each share's guest inode and
ctime views. Import validates the whole manifest before creating an
exclusive 0700 destination, journals every created name with its
identity, and removes only its own names on failure.

Capture refuses up front without CAP_SYS_ADMIN in the initial user
namespace, since trusted.* xattrs would otherwise be silently dropped.
A device reset now ends a pending restored session, returns the DAX
window to zero memory (or retires the device when the window is lost)
and keeps serving the archived init.krun.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
RamSnapshotVm can now attach up to seven virtio-fs shares, pause them
with the other devices, export them into full image v7 and import them
from an independent copy. The image appends the archive's file, init.krun
and DAX page payloads after the disk segments; metadata validates RAM
regions before device sections and checks the exact total length.
Imports need fs_dir exactly when the image has shares, and exports need
declare_host_writers_stopped and CAP_SYS_ADMIN in the initial user
namespace.

An owner with a DAX window runs every KVM_RUN under an execution barrier
that also controls every host mapping call on the window, so no vCPU
runs while a remap is in progress and none runs again after one fails.
Ranges a failed MAP_FIXED may have unmapped stay reserved for the life
of the process. Devices now retire instead of resetting on teardown,
and a failed map_dax retires the device.

KVM execution of the owner paths remains unverified (no /dev/kvm).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Support production Linux boot and portable KRUNVM v8 checkpoints with

guest-visible filesystem archives, retained DAX mappings, and a C control

ABI for pause, export, import, resume, and stop.

KVM runtime acceptance remains unverified; non-KVM checks and static

linkage evidence are documented with the implementation.
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: QUIET
  • Plan: Advanced
  • Run ID: b93e6394-05eb-4280-bd8c-6c0ca0e07ac2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

lfld287 and others added 4 commits October 26, 2026 18:38
A checkpointing VM puts its disks on GSIs 16-22 and its NIC on GSI 23,
but the MP table only gave interrupt sources for IOAPIC inputs 0-15.
Linux allocates no IRQ for an input the table leaves out, so the
virtio-blk and virtio-net drivers fail request_irq with EINVAL, the
root disk never appears and the guest's init exits at boot.

Describe all 24 inputs of KVM's in-kernel IOAPIC, which KVM's default
routing wires to the GSIs of the same number. The ordinary VMM keeps
its devices on GSIs 5-15; the extra inputs carry no device.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A checkpointing VM's kernel boot configured its vCPUs like the ordinary
VMM, with the full supported CPUID. On a host with XSAVES (or CET,
AMX, PT and the other features whose state a snapshot does not carry)
every export then failed: "CPU exposes extended state outside the
snapshot contract". Only the device-free minimal VM hid those features.

The snapshot boot now hides them before setting the CPUID and the boot
registers, through the same mask the minimal VM uses, so the guest
never enables state an export would refuse.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Export compared the guest's leaf 1, 7 and 0x80000001 feature bits with
KVM_GET_SUPPORTED_CPUID. That list never contains the hypervisor and
TSC-deadline bits (leaf 1 ECX) or HTT (leaf 1 EDX), which the VMM sets
itself, so every export of a booted guest failed with "actual CPUID
exposes unsupported target feature".

Accept exactly those three bits, as QEMU does when it computes the
CPUID a KVM guest may expose; TSC-deadline rests on the in-kernel
irqchip and TSC-deadline capabilities the snapshot already requires.
Every other bit the target lacks is still refused.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Importing a checkpoint on the very host that exported it failed with
"incompatible CPU vendor/features, MSRs, XSAVE layout or KVM
capabilities". KVM_GET_SUPPORTED_CPUID runs CPUID on whichever host CPU
makes the call and passes that CPU's APIC IDs through in leaf 1
EBX[31:24] and leaf 0xB/0x1F EDX, so the export and the import captured
different values whenever they ran on different CPUs.

Compare the supported CPUID with those fields cleared; every feature,
the XSAVE layout, the MSRs and the KVM capabilities stay exact.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@lfld287

lfld287 commented Oct 27, 2026

Copy link
Copy Markdown
Author

/reviewed 96c0ca3

@lfld287
lfld287 marked this pull request as ready for review October 27, 2026 08:20

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Store memory and device state separately from the standalone QCOW2 disk.
Restore external resources through explicit descriptors and preserve
capture ownership, cancellation, and device continuation contracts.
Record unlink eligibility and omit unavailable objects and handles during restore while preserving guest ID allocation counters. Keep DAX backing and invalid bindings strict.
ltstriker pushed a commit to boxlite-ai/boxlite that referenced this pull request Oct 28, 2026
## TL;DR

Add two-file VM checkpoints with local and REST import/export.

Design doc: #2111

Depends on: boxlite-ai/libkrun#3

Documentation: [checkpoint
guide](https://github.com/lfld287/boxlite/blob/cf7b159f/docs/guides/checkpoints.md)

Size exception: approved for this integration.

## How it works

Paused guests export memory and standalone QCOW2 files. Imports recover
target mounts and preserve guest processes. REST imports enforce server
host-path permissions. Disk snapshots coexist with checkpoints; archive
restore retains support for never-started boxes.

## Verification

`cargo check -p boxlite-cli -p boxlite-node --tests --offline` and `make
fmt:check:rust` passed. Checkpoint tests encountered sandbox-denied Unix
sockets; the suite did not pass. KVM acceptance was not rerun on this
head.

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
@ltstriker
ltstriker merged commit eacc884 into boxlite-ai:x_features Oct 28, 2026
1 check passed
DefeatMan pushed a commit to boxlite-ai/boxlite that referenced this pull request Oct 29, 2026
Add two-file VM checkpoints with local and REST import/export.

Design doc: #2111

Depends on: boxlite-ai/libkrun#3

Documentation: [checkpoint
guide](https://github.com/lfld287/boxlite/blob/cf7b159f/docs/guides/checkpoints.md)

Size exception: approved for this integration.

Paused guests export memory and standalone QCOW2 files. Imports recover
target mounts and preserve guest processes. REST imports enforce server
host-path permissions. Disk snapshots coexist with checkpoints; archive
restore retains support for never-started boxes.

`cargo check -p boxlite-cli -p boxlite-node --tests --offline` and `make
fmt:check:rust` passed. Checkpoint tests encountered sandbox-denied Unix
sockets; the suite did not pass. KVM acceptance was not rerun on this
head.

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants