Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f763d61
Refactor SandboxMemoryLayout
ludfjig Apr 7, 2026
d58ed12
Move sandbox snapshot.rs into snapshot module dir
ludfjig May 1, 2026
b60bb6f
Remove unused get_file_mappings_pointer_offset
ludfjig May 1, 2026
6f9cab9
Expose SandboxMemoryLayout fields to crate
ludfjig May 1, 2026
8d4ffd7
Extract HyperlightVm apply_sregs helper
ludfjig May 1, 2026
dc0d08b
Introduce HostFunctions newtype for sandbox construction
ludfjig May 1, 2026
8152f0f
Add file backed ReadonlySharedMemory
ludfjig May 1, 2026
ea7fb93
Persist host function metadata in Snapshot
ludfjig May 1, 2026
5d80eac
Make gdb work for already initialised snapshots
ludfjig May 1, 2026
9d00b24
Add MultiUseSandbox from_snapshot
ludfjig May 1, 2026
e37900b
Add snapshot file format with persistence and load
ludfjig May 1, 2026
9e0334c
Add tests for snapshot file format
ludfjig May 1, 2026
7fd38b1
Add snapshot file benchmarks
ludfjig May 1, 2026
621cc03
Add gdb test for MultiUseSandbox from_snapshot
ludfjig May 1, 2026
033c551
WIP: snapshot ABI tripwires + golden tests
ludfjig May 8, 2026
3a6f6f4
WIP: cross-load helpers + workflow upload glob + bypass env var
ludfjig May 11, 2026
26bb3ab
WIP: fix fetch-snapshot-goldens on Windows (Test-Path guard)
ludfjig May 11, 2026
f1ce942
WIP: normalize segment hidden-cache fields on snapshot write
ludfjig May 11, 2026
e7bd956
WIP: snapshot goldens: split fixtures by hv/cpu/profile + cross-load CI
ludfjig May 11, 2026
a184c22
WIP: add 24 snapshot golden fixtures (3 hv * 2 cpu * 2 profile * 2 ki…
ludfjig May 11, 2026
ca8c992
WIP: build-test fail-fast=false; cross-load goldens covers self-cell too
ludfjig May 11, 2026
491a35d
WIP: normalize tr.type busy bit; cross-load skip self-cell
ludfjig May 11, 2026
d40106d
WIP: regen call goldens with normalized tr.type
ludfjig May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions .github/workflows/RegenSnapshotGoldens.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json

name: Regenerate Snapshot Goldens

on:
pull_request:
types: [labeled]

permissions:
contents: read
pull-requests: read

defaults:
run:
shell: bash

jobs:
# Build guests once per config, upload as artifacts for the regen
# jobs to download. Mirrors `build-guests` in
# `ValidatePullRequest.yml`. Both debug and release simpleguest
# binaries are needed because the captured memory blob differs
# between them, so each ends up in a separate fixture cell.
build-guests:
if: github.event.label.name == 'regen-goldens'
strategy:
fail-fast: false
matrix:
config: [debug, release]
uses: ./.github/workflows/dep_build_guests.yml
secrets: inherit
with:
docs_only: "false"
config: ${{ matrix.config }}

regen:
if: github.event.label.name == 'regen-goldens'
needs: [build-guests]
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
hypervisor: ['hyperv-ws2025', mshv3, kvm]
cpu: [amd, intel]
config: [debug, release]
runs-on: ${{ fromJson(
format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}", "JobId=regen-goldens-{3}-{4}-{5}-{6}-{7}"]',
matrix.hypervisor == 'hyperv-ws2025' && 'Windows' || 'Linux',
matrix.hypervisor == 'hyperv-ws2025' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
matrix.cpu,
matrix.hypervisor,
matrix.config,
github.run_id,
github.run_number,
github.run_attempt)) }}
steps:
- uses: actions/checkout@v6

- uses: hyperlight-dev/ci-setup-workflow@v1.9.0
with:
rust-toolchain: "1.89"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Fix cargo home permissions
if: runner.os == 'Linux'
run: |
sudo chown -R $(id -u):$(id -g) /opt/cargo || true

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: "${{ runner.os }}-${{ matrix.config }}"
cache-on-failure: "true"

- name: Download Rust guests
uses: actions/download-artifact@v8
with:
name: rust-guests-${{ matrix.config }}
path: src/tests/rust_guests/bin/${{ matrix.config }}/

- name: Run regen
env:
HYPERLIGHT_REGEN_GOLDENS: "1"
run: |
cargo test --profile=${{ matrix.config == 'debug' && 'dev' || matrix.config }} \
-p hyperlight-host --lib \
sandbox::snapshot::golden_tests::golden_regen \
-- --nocapture

- name: Upload regenerated fixtures
uses: actions/upload-artifact@v4
with:
name: goldens-${{ matrix.hypervisor }}-${{ matrix.cpu }}-${{ matrix.config }}
# Restrict the glob to fixtures matching this cell's
# `{hv}_{cpu}_{config}` suffix. mshv3 maps to the `mshv`
# filename suffix, hyperv-ws2025 maps to `whp`.
path: |
src/hyperlight_host/tests/snapshot_goldens/fixtures/*_${{ matrix.hypervisor == 'mshv3' && 'mshv' || matrix.hypervisor == 'hyperv-ws2025' && 'whp' || matrix.hypervisor }}_${{ matrix.cpu }}_${{ matrix.config }}.hls
if-no-files-found: error
retention-days: 14
2 changes: 1 addition & 1 deletion .github/workflows/ValidatePullRequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:
# See: https://github.com/actions/runner/issues/2205
if: ${{ !cancelled() && !failure() }}
strategy:
fail-fast: true
fail-fast: false
matrix:
hypervisor: ['hyperv-ws2025', mshv3, kvm]
cpu: [amd, intel]
Expand Down
44 changes: 44 additions & 0 deletions .github/workflows/dep_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,50 @@ jobs:
# with default features
just test ${{ inputs.config }}

- name: Cross-load snapshot goldens from every (hv, cpu, profile) cell
# The committed snapshot fixtures are tagged
# `{hv}_{cpu}_{config}`. This step iterates every committed
# cell, copies its `init`/`call` pair over the local-suffix
# slot and runs the goldens with
# `HYPERLIGHT_SNAPSHOT_BYPASS_VALIDATION=1` so the
# hv-tag/hash mismatch in foreign files does not fail the
# load. Exercises that the on-disk format is portable across
# HVs, CPU vendors, and guest build profiles. Missing fixture
# cells are warned about but skipped so the step is
# forward-compatible while regen catches up.
env:
HYPERLIGHT_SNAPSHOT_BYPASS_VALIDATION: "1"
run: |
case "${{ inputs.hypervisor }}" in
mshv3) LOCAL_HV=mshv ;;
hyperv-ws2025) LOCAL_HV=whp ;;
*) LOCAL_HV=kvm ;;
esac
LOCAL_SUFFIX="${LOCAL_HV}_${{ inputs.cpu }}_${{ inputs.config }}"
FIX=src/hyperlight_host/tests/snapshot_goldens/fixtures
PROFILE=${{ inputs.config == 'debug' && 'dev' || inputs.config }}
for hv in kvm mshv whp; do
for cpu in intel amd; do
for cfg in debug release; do
SRC_SUFFIX="${hv}_${cpu}_${cfg}"
# Local cell is already exercised by the regular
# `just test` step above; skipping here also avoids
# the `cp` self-copy error.
if [ "$SRC_SUFFIX" = "$LOCAL_SUFFIX" ]; then continue; fi
if [ ! -f "$FIX/init_${SRC_SUFFIX}.hls" ] || [ ! -f "$FIX/call_${SRC_SUFFIX}.hls" ]; then
echo "::warning::missing fixture pair for ${SRC_SUFFIX}, skipping cross-load"
continue
fi
echo "::group::cross-load source=${SRC_SUFFIX} into local=${LOCAL_SUFFIX}"
cp -f "$FIX/init_${SRC_SUFFIX}.hls" "$FIX/init_${LOCAL_SUFFIX}.hls"
cp -f "$FIX/call_${SRC_SUFFIX}.hls" "$FIX/call_${LOCAL_SUFFIX}.hls"
cargo test --profile=$PROFILE -p hyperlight-host --lib sandbox::snapshot::golden_tests
echo "::endgroup::"
done
done
done
git checkout -- "$FIX"

- name: Run Rust tests with single driver
if: runner.os == 'Linux'
run: |
Expand Down
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -572,3 +572,54 @@ install-vcpkg:

install-flatbuffers-with-vcpkg: install-vcpkg
cd ../vcpkg && ./vcpkg install flatbuffers || cd -

##################################
### SNAPSHOT GOLDEN CROSS-LOAD ###
##################################
# Cross-HV/CPU experiment helpers. Pull the `.hls` fixtures
# generated by a specific run of the `Regenerate Snapshot Goldens`
# workflow, drop them into the local fixtures dir under the
# locally-detected hypervisor's name, and run the goldens with
# validation bypassed so the HV-tag mismatch in the file does not
# fail the load.
#
# Requires: `gh` CLI authenticated to the repo. The CI run id is
# the run that produced the artifacts you want (find it under the
# Actions tab of the PR).

# Fetch all `goldens-*` artifacts from a regen workflow run into
# `target/snapshot-goldens-cross-load/`. Run id is the only arg.
#
# Example:
# just fetch-snapshot-goldens 25583983652
fetch-snapshot-goldens run_id:
{{ if os() == "windows" { "if (Test-Path target/snapshot-goldens-cross-load) { Remove-Item -Recurse -Force target/snapshot-goldens-cross-load }" } else { "rm -rf target/snapshot-goldens-cross-load" } }}
{{ if os() == "windows" { "New-Item -ItemType Directory -Force target/snapshot-goldens-cross-load | Out-Null" } else { "mkdir -p target/snapshot-goldens-cross-load" } }}
gh run download {{run_id}} --dir target/snapshot-goldens-cross-load -p 'goldens-*'
ls target/snapshot-goldens-cross-load/

# Cross-load test: copy the chosen artifact's `.hls` files over
# the locally-named fixtures and run goldens with validation
# bypassed so the HV-tag mismatch (and the resulting hash
# mismatch) does not fail the load.
#
# `source` is the artifact dir name produced by the regen
# workflow, e.g. `goldens-kvm-amd-debug`. `source_suffix` is the
# `{hv}_{cpu}_{config}` suffix of the files inside that artifact
# (e.g. `kvm_amd_debug`; mshv3 -> `mshv`, hyperv-ws2025 -> `whp`).
# `local_suffix` is the `{hv}_{cpu}_{config}` suffix the local
# `golden_tests` detection will look for on this machine.
#
# Example (load AMD-on-KVM-debug CI artifact on a local Intel KVM
# debug box):
# just cross-load-snapshot-goldens goldens-kvm-amd-debug kvm_amd_debug kvm_intel_debug
#
# Example (load Intel-on-MSHV-release CI artifact on a local
# KVM-debug box):
# just cross-load-snapshot-goldens goldens-mshv3-intel-release mshv_intel_release kvm_intel_debug
cross-load-snapshot-goldens source source_suffix local_suffix:
{{ if os() == "windows" { "Copy-Item -Force target/snapshot-goldens-cross-load/" + source + "/init_" + source_suffix + ".hls src/hyperlight_host/tests/snapshot_goldens/fixtures/init_" + local_suffix + ".hls" } else { "cp target/snapshot-goldens-cross-load/" + source + "/init_" + source_suffix + ".hls src/hyperlight_host/tests/snapshot_goldens/fixtures/init_" + local_suffix + ".hls" } }}
{{ if os() == "windows" { "Copy-Item -Force target/snapshot-goldens-cross-load/" + source + "/call_" + source_suffix + ".hls src/hyperlight_host/tests/snapshot_goldens/fixtures/call_" + local_suffix + ".hls" } else { "cp target/snapshot-goldens-cross-load/" + source + "/call_" + source_suffix + ".hls src/hyperlight_host/tests/snapshot_goldens/fixtures/call_" + local_suffix + ".hls" } }}
{{ if os() == "windows" { "$env:HYPERLIGHT_SNAPSHOT_BYPASS_VALIDATION = '1'; cargo test -p hyperlight-host --lib sandbox::snapshot::golden_tests" } else { "HYPERLIGHT_SNAPSHOT_BYPASS_VALIDATION=1 cargo test -p hyperlight-host --lib sandbox::snapshot::golden_tests" } }}
git checkout src/hyperlight_host/tests/snapshot_goldens/fixtures/

Loading
Loading