Open
Conversation
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
84873d3 to
7f499c8
Compare
Save snapshots to disk via Snapshot::to_file(), load them back via Snapshot::from_file(). Create sandboxes directly from loaded snapshots via MultiUseSandbox::from_snapshot(), bypassing ELF parsing and guest init. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds first-class support for persisting Snapshots to disk and rehydrating sandboxes from those snapshots to avoid ELF parsing / guest init on cold start, using file-backed mappings for (near) zero-copy loads.
Changes:
- Implement
Snapshot::to_file(),Snapshot::from_file(), andSnapshot::from_file_unchecked()with a versioned on-disk header + mmappable memory blob. - Add
MultiUseSandbox::from_snapshot()fast-path for sandbox creation directly from an in-memory or disk-loaded snapshot. - Introduce file-backed
ReadonlySharedMemory::from_file()and refactorSandboxMemoryLayoutto expose enough stable layout fields for serialization.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/hyperlight_host/src/sandbox/uninitialized_evolve.rs | Updates layout API usage (peb_address() accessor). |
| src/hyperlight_host/src/sandbox/uninitialized.rs | Ensures snapshot-based sandbox creation registers default HostPrint via FunctionRegistry::with_default_host_print(). |
| src/hyperlight_host/src/sandbox/snapshot.rs | Defines snapshot file format + (de)serialization, file load/save APIs, sregs I/O, and extensive tests. |
| src/hyperlight_host/src/sandbox/initialized_multi_use.rs | Adds MultiUseSandbox::from_snapshot() instantiation path. |
| src/hyperlight_host/src/sandbox/host_funcs.rs | Adds FunctionRegistry::with_default_host_print() helper and makes default writer private. |
| src/hyperlight_host/src/mem/shared_mem.rs | Adds ReadonlySharedMemory::from_file() for file-backed snapshot memory mappings. |
| src/hyperlight_host/src/mem/mgr.rs | Updates layout field access for scratch I/O buffer sizes. |
| src/hyperlight_host/src/mem/memory_region.rs | Routes Snapshot regions through the Windows surrogate “ReadOnlyFile” mapping path. |
| src/hyperlight_host/src/mem/layout.rs | Refactors SandboxMemoryLayout to store key sizes directly and computes offsets via methods; updates PEB writing. |
| src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs | Factors out apply_sregs() and updates peb_address() usage. |
| src/hyperlight_host/benches/benchmarks.rs | Adds benchmarks for snapshot file save/load and cold start via snapshot. |
| src/hyperlight_common/src/mem.rs | Adds write_to() helpers for GuestMemoryRegion and HyperlightPEB. |
| docs/snapshot-file-implementation-plan.md | Adds a detailed design/format plan and future work notes. |
Comment on lines
+954
to
+958
| fn write_sregs(w: &mut impl std::io::Write, sregs: &CommonSpecialRegisters) -> crate::Result<()> { | ||
| // Segment registers: cs, ds, es, fs, gs, ss, tr, ldt (13 fields each) | ||
| for seg in [ | ||
| &sregs.cs, &sregs.ds, &sregs.es, &sregs.fs, &sregs.gs, &sregs.ss, &sregs.tr, &sregs.ldt, | ||
| ] { |
Comment on lines
+897
to
+901
| let input_data_size = read_u64(r)? as usize; | ||
| let output_data_size = read_u64(r)? as usize; | ||
| let heap_size = read_u64(r)? as usize; | ||
| let code_size = read_u64(r)? as usize; | ||
| let init_data_size = read_u64(r)? as usize; |
Comment on lines
+906
to
+913
| Some( | ||
| MemoryRegionFlags::from_bits(perms_raw as u32).ok_or_else(|| { | ||
| crate::new_error!( | ||
| "snapshot contains unknown memory region flags: {:#x}", | ||
| perms_raw | ||
| ) | ||
| })?, | ||
| ) |
| } else { | ||
| None | ||
| }; | ||
|
|
Comment on lines
+2044
to
+2048
| /// - **Windows**: `CreateFileMappingA(PAGE_WRITECOPY)` + | ||
| /// `MapViewOfFile(FILE_MAP_COPY)` for zero-copy file-backed CoW. | ||
| /// The returned `HostMapping` carries the file mapping handle so | ||
| /// the surrogate process can create its own view via | ||
| /// `MapViewOfFileNuma2`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Save snapshots to disk via
Snapshot::to_file(), load them viaSnapshot::from_file(). Create sandboxes directly from loaded snapshots viaMultiUseSandbox::from_snapshot(), bypassing ELF parsing and guest init. No memcpy needed!With this PR I'm hoping to gather feedback on design, and also start a discussion about what features is necessary before we can release this. For example currently it's impossible to register any host functions on sandboxes created directly from snapshots, and probably a builder pattern could fix this (something like
.with_host_func(hostfunc))