Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9b775b8
nix: Support developing on macOS
syntactically Jul 20, 2026
a027292
Reduce duplication of interrupt handle state machines
syntactically Jul 6, 2026
a8d5f97
Abstract out interrupt handle retry logic
syntactically Jul 20, 2026
6b29452
Be more careful about cfg(target_os = "linux") vs cfg(unix)
syntactically Jul 6, 2026
f590547
hvf: add cfg items and detection stub
syntactically Jul 6, 2026
8aba46e
hvf: add Rust bindings
syntactically Jul 6, 2026
715ac72
hvf: add interrupt handle using `hv_vcpus_exit`
syntactically Jul 6, 2026
11f85e7
Disentangle host and guest page sizes
syntactically Jul 7, 2026
554f478
Change guest layout to support 16k host pages
syntactically Jul 15, 2026
96f2655
Make VirtualMachine::set_{regs,sregs,fpu} take &mut
syntactically Aug 10, 2026
819c50d
fixup! Reduce duplication of interrupt handle state machines
syntactically Aug 10, 2026
6f72496
[tests] hvf: support identifiers and reduce thread counts
syntactically Jul 20, 2026
9bd34ee
Restrict usage of MIDR_EL1 to Linux
syntactically Jul 20, 2026
a798cfc
Initial single-address-space support for Hypervisor.framework
syntactically Jul 20, 2026
41bdec0
cargo: Add codesigning runner script for MacOS
syntactically Jul 20, 2026
9fd6c64
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
c9c1e33
aarch64: Move machinery for decoding ESR_ELx to hyperlight-common
syntactically Aug 1, 2026
443068e
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
f483541
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
c8eee02
fixup! Abstract out interrupt handle retry logic
syntactically Aug 1, 2026
a8658a3
fixup! Reduce duplication of interrupt handle state machines
syntactically Aug 1, 2026
51088c4
fixup! Disentangle host and guest page sizes
syntactically Aug 1, 2026
f9768dd
fixup! hvf: add Rust bindings
syntactically Aug 1, 2026
20f7a68
ci: enable running on MacOS/HVF
syntactically Aug 1, 2026
b369657
fixup! hvf: add Rust bindings
syntactically Aug 1, 2026
3451a0b
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
e700eda
fixup! Disentangle host and guest page sizes
syntactically Aug 1, 2026
444045c
amend! [tests] hvf: support identifiers and reduce thread counts
syntactically Aug 2, 2026
fb504b4
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 2, 2026
8401d42
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 3, 2026
9e14452
fixup! ci: enable running on MacOS/HVF
syntactically Aug 3, 2026
62d3478
fixup! Change guest layout to support 16k host pages
syntactically Aug 3, 2026
83b696a
Convert mem::shared_mem module to use thiserror structured errors
syntactically Aug 10, 2026
c8d2e47
fixup! hvf: add interrupt handle using `hv_vcpus_exit`
syntactically Aug 10, 2026
41a5382
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 10, 2026
27d523d
fixup! aarch64: Move machinery for decoding ESR_ELx to hyperlight-common
syntactically Aug 11, 2026
ea31954
fixup! Abstract out interrupt handle retry logic
syntactically Aug 11, 2026
eaf228c
fixup! Be more careful about cfg(target_os = "linux") vs cfg(unix)
syntactically Aug 11, 2026
9546a16
fixup! ci: enable running on MacOS/HVF
syntactically Aug 11, 2026
544291f
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 11, 2026
85f33b9
fixup! Convert mem::shared_mem module to use thiserror structured errors
syntactically Aug 11, 2026
813a8c3
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 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
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.'cfg(target_os = "macos")']
runner = "dev/macos-sign-and-run.sh"
6 changes: 4 additions & 2 deletions .github/workflows/DailyArm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ jobs:
fail-fast: false
matrix:
config: [debug, release]
hypervisor: [hvf, kvm]
uses: ./.github/workflows/dep_build_test.yml
secrets: inherit
with:
hypervisor: kvm
hypervisor: ${{ matrix.hypervisor }}
cpu_vendor: apple
arch: arm64
config: ${{ matrix.config }}
Expand All @@ -65,10 +66,11 @@ jobs:
fail-fast: false
matrix:
config: [debug, release]
hypervisor: [hvf, kvm]
uses: ./.github/workflows/dep_run_examples.yml
secrets: inherit
with:
hypervisor: kvm
hypervisor: ${{ matrix.hypervisor }}
cpu_vendor: apple
arch: arm64
config: ${{ matrix.config }}
Expand Down
29 changes: 15 additions & 14 deletions .github/workflows/RegenSnapshotGoldens.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ jobs:
strategy:
fail-fast: false
matrix:
hypervisor: [kvm, mshv3, hyperv-ws2025]
hypervisor: [kvm, mshv3, hyperv-ws2025, hvf]
cpu: [amd, intel, apple]
arch: [X64, arm64]
config: [debug, release]
Expand All @@ -148,25 +148,26 @@ jobs:
hypervisor: mshv3
- cpu: apple
hypervisor: hyperv-ws2025
- arch: X64
hypervisor: hvf
- cpu: apple
arch: X64
- cpu: amd
arch: arm64
- cpu: intel
arch: arm64
runs-on: ${{ fromJson(
format('["self-hosted", "{0}", "{1}"{2}]',
matrix.hypervisor == 'hyperv-ws2025' && 'Windows' || 'Linux',
matrix.arch,
matrix.arch == 'X64'
&& format(', "1ES.Pool=hld-{0}-{1}", "JobId=regen-goldens-{2}-{3}-{4}-{5}"',
matrix.hypervisor == 'hyperv-ws2025' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
matrix.cpu,
matrix.config,
github.run_id,
github.run_number,
github.run_attempt)
|| ', "kvm", "ubuntu-24.04"')) }}
runs-on: ${{ fromJson(matrix.arch == 'X64'
&& format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}", "JobId=regen-goldens-{3}-{4}-{5}-{6}"]',
matrix.hypervisor == 'hyperv-ws2025' && 'Windows' || 'Linux',
matrix.hypervisor == 'hyperv-ws2025' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
matrix.cpu,
matrix.config,
github.run_id,
github.run_number,
github.run_attempt)
|| format('["self-hosted", "{0}", "arm64", "{1}"]',
matrix.hypervisor == 'hvf' && 'macos' || 'Linux',
matrix.hypervisor)) }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/ValidatePullRequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ jobs:
strategy:
fail-fast: true
matrix:
hypervisor: ['hyperv-ws2025', mshv3, kvm]
hypervisor: ['hyperv-ws2025', mshv3, kvm, hvf]
cpu_vendor: [amd, intel, apple]
arch: [X64, arm64]
config: [debug, release]
Expand All @@ -158,6 +158,8 @@ jobs:
hypervisor: hyperv-ws2025
- cpu_vendor: apple
hypervisor: mshv3
- arch: X64
hypervisor: hvf
- cpu_vendor: amd
arch: arm64
- cpu_vendor: intel
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/dep_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ jobs:
github.run_id,
github.run_number,
github.run_attempt)
|| '["self-hosted", "Linux", "arm64", "kvm", "ubuntu-24.04"]') }}
|| format('["self-hosted", "{0}", "arm64", "{1}"]',
inputs.hypervisor == 'hvf' && 'macos' || 'Linux',
inputs.hypervisor)) }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
MSRs, on MSHV and WHP this is not enforced. by @ludfjig in https://github.com/hyperlight-dev/hyperlight/pull/991
* **Breaking:** Filesystem paths are now represented using `PathBuf`. `GuestBinary::FilePath` now stores a `PathBuf` instead of a `String`, and `MultiUseSandbox::generate_crashdump_to_dir` accepts `Into<PathBuf>` instead of `Into<String>`. Callers passing a `String` to `GuestBinary::FilePath` must convert it using `.into()`.

Certain fixed guest addresses were changed on AArch64 to more easily
accommodate 16k pages without wasting memory. Snapshots taken from
sandboxes using the old addresses will not be loadable by new
hyperlight versions.

Comment on lines +17 to +21

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To me it sounds like only old aarch64 snapshot are no longer loadable which might be a bit confusing. Also should we make this a bullet?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The aarch64 ones are the only ones that actually changed in layout, so I think this is more accurate. (I bumped the global version because it seems difficult with the current infrastructure to make the change arch-specific, and as far as I know nobody is depending on snapshot compatibility yet (since we don't really have any guest ABI compatibility guarantees pre-1.0))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ah ok

### Removed

### Fixed
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ snapshot-goldens-pull target=default-target which="all" image=default-snapshot-g
if [[ -e /dev/mshv ]]; then hv=mshv
elif [[ -e /dev/kvm ]]; then hv=kvm
elif [[ "${OS:-}" == "Windows_NT" ]]; then hv=whp
elif [[ "$(sysctl -n kern.hv_support)" == "1" ]]; then hv=hvf
else echo "snapshot-goldens-pull: no hypervisor found" >&2; exit 1
fi
# Mirror of `CpuVendor::golden_tag` in file/config.rs. x86_64 reads
Expand Down
8 changes: 8 additions & 0 deletions dev/macos-entitlements.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.hypervisor</key>
<true/>
</dict>
</plist>
6 changes: 6 additions & 0 deletions dev/macos-sign-and-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -Eeuo pipefail


codesign -f -s - --entitlements "$(dirname "$0")/macos-entitlements.plist" "$1"
exec "$@"
6 changes: 3 additions & 3 deletions flake.lock

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

34 changes: 18 additions & 16 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
orig = super.rustChannelOf args;
patchRustPkg = pkg: (pkg.overrideAttrs (oA: {
buildCommand = (builtins.replaceStrings
[ "rustc,rustdoc" ]
[ "rustc,rustdoc,clippy-driver,cargo-clippy,miri,cargo-miri" ]
[ "rustc,rustdoc" "librustc_driver-*.so" ]
[ "rustc,rustdoc,clippy-driver,cargo-clippy,miri,cargo-miri" "librustc_driver-*.{so,dylib}" ]
oA.buildCommand) + (let
wrapperPath = self.path + "/pkgs/build-support/bintools-wrapper/ld-wrapper.sh";
baseOut = self.clangStdenv.cc.bintools.out;
Expand Down Expand Up @@ -51,7 +51,7 @@
toolchainVersionAttrs = args;
};
})) // {
targetPlatforms = [ "aarch64-linux" "x86_64-linux" ];
targetPlatforms = [ "aarch64-linux" "x86_64-linux" "aarch64-darwin" ];
badTargetPlatforms = [ ];
};
overrideRustPkg = pkg: self.lib.makeOverridable (origArgs:
Expand Down Expand Up @@ -82,7 +82,7 @@
"x86_64-unknown-linux-gnu"
"x86_64-pc-windows-msvc" "x86_64-unknown-none"
"wasm32-wasip1" "wasm32-wasip2" "wasm32-unknown-unknown"
"aarch64-unknown-none"
"aarch64-unknown-none" "aarch64-apple-darwin"
];
extensions = [ "rust-src" ] ++ (if args.channel == "nightly" then [ "miri-preview" ] else []);
});
Expand Down Expand Up @@ -166,13 +166,14 @@
esac
if [ -f ''${root}/flake.nix ]; then

mkdir -p $root/$.cargo
cat >$root/.cargo/config.toml <<EOF
[source.crates-io]
replace-with = "vendored-sources"
sed -i '/# vendor dependency configuration generated by nix/{N;N;N;N;N;d;}' $root/.cargo/config.toml
cat >>$root/.cargo/config.toml <<EOF
# vendor dependency configuration generated by nix
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "${deps}"
[source.vendored-sources]
directory = "${deps}"
EOF

sed -i '/# vendor dependency configuration generated by nix/{N;d;}' $root/.git/info/exclude
Expand Down Expand Up @@ -228,14 +229,14 @@

cargo-hyperlight = buildRustPackageClang rec {
pname = "cargo-hyperlight";
version = "0.1.5";
version = "0.1.14-pre";
src = fetchFromGitHub {
owner = "hyperlight-dev";
repo = "cargo-hyperlight";
rev = "28ac7b57e8e7b83f80bd601f1fab334aa3ae6d4a";
hash = "sha256-a/mvPEDJycrCbmd826SmFdasE8BFtMkCsefCNR5JnkM=";
rev = "33384c0c4ed9dea4f0525943809fc444c41a27df";
hash = "sha256-A2/SNHCdPPzW86bd00IucZEyZHZWDqXVKPccZULcEu0=";
};
cargoHash = "sha256-wLapaao8qcB/toltV/xjQ7SXXcfh2J19nw6jWljmb2s=";
cargoHash = "sha256-ImWnNzXvDKokML0BDyyjifrZ1bnG6ymXt5vAMRIpwUY==";
doCheck = false;
};
in (buildRustPackageClang (mkDerivationAttrs: {
Expand All @@ -251,7 +252,6 @@
llvmPackages_18.llvm
gh
lld
valgrind
pkg-config
ffmpeg
mkvtoolnix
Expand All @@ -264,7 +264,9 @@
typos
flatbuffers
cargo-fuzz
];
] ++ (if system == "x86_64-linux" || system == "aarch64-linux"
then [ valgrind ]
else []);
buildInputs = [
pango
cairo
Expand Down
100 changes: 100 additions & 0 deletions src/hyperlight_common/src/arch/aarch64/exn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
Copyright 2026 The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

use crate::vmem::bits;

const ESR_EC_DATA_ABORT_LOWER_EL: u64 = 0b100100;
const ESR_EC_DATA_ABORT_SAME_EL: u64 = 0b100101;

// some of the data in these is not used presently, but is logically
// part of the code being decoded & should be accounted for
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub enum DataFaultKind {
TranslationFault(i64),
PermissionFault(i64),
Other(u64),
}
fn decode_data_fault_status_code(dfsc: u64) -> DataFaultKind {
if bits::<5, 2>(dfsc) == 0b0011 {
DataFaultKind::PermissionFault(bits::<1, 0>(dfsc) as i64)
} else if bits::<5, 2>(dfsc) == 0b0001 {
DataFaultKind::TranslationFault(bits::<1, 0>(dfsc) as i64)
} else if bits::<5, 2>(dfsc) == 0b1010 {
if bits::<1, 0>(dfsc) >= 2 {
DataFaultKind::TranslationFault(bits::<1, 0>(dfsc) as i64 - 4)
} else {
DataFaultKind::Other(dfsc)
}
} else {
DataFaultKind::Other(dfsc)
}
}

#[derive(Debug, Copy, Clone)]
pub struct DataFaultInstructionSyndrome {
pub srt: u8,
// ...
}
fn decode_data_fault_instruction_syndrome(iss: u64) -> Option<DataFaultInstructionSyndrome> {
let isv = bits::<24, 24>(iss);
if isv != 0b1 {
return None;
}
Some(DataFaultInstructionSyndrome {
srt: bits::<20, 16>(iss) as u8,
})
}

#[derive(Debug, Copy, Clone)]
pub struct DataFault {
pub from_lower_el: bool,
pub is_s1ptw: bool,
pub is_write: bool,
pub kind: DataFaultKind,
pub insn: Option<DataFaultInstructionSyndrome>,
}

fn decode_data_fault(from_lower_el: bool, iss: u64) -> DataFault {
DataFault {
from_lower_el,
is_s1ptw: bits::<7, 7>(iss) == 0b1,
is_write: bits::<6, 6>(iss) == 0b1,
kind: decode_data_fault_status_code(bits::<5, 0>(iss)),
insn: decode_data_fault_instruction_syndrome(iss),
}
}

// some of the data in these is not used presently, but is logically
// part of the code being decoded & should be accounted for
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub enum Exception {
/// lower el?, faulting address, status code
DataFault(DataFault),
Other(u64),
}
/// Decode the value of ESR_ELx into a nice enum. Also takes FAR_ELx,
/// which will be embedded in the structure if relevant.
pub fn decode_syndrome(esr: u64) -> Exception {
let ec = bits::<31, 26>(esr);
match ec {
ESR_EC_DATA_ABORT_LOWER_EL | ESR_EC_DATA_ABORT_SAME_EL => Exception::DataFault(
decode_data_fault(ec == ESR_EC_DATA_ABORT_LOWER_EL, bits::<24, 0>(esr)),
),
_ => Exception::Other(esr),
}
}
2 changes: 1 addition & 1 deletion src/hyperlight_common/src/arch/aarch64/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ limitations under the License.
pub const SCRATCH_TOP_GVA: usize = 0x0000_ffff_ffff_dfff;
pub const SNAPSHOT_PT_GVA_MIN: usize = 0x0000_8000_0000_0000;
pub const SNAPSHOT_PT_GVA_MAX: usize = 0x0000_80ff_ffff_ffff;
pub const SCRATCH_TOP_GPA: usize = 0x0000_000f_ffff_efff;
pub const SCRATCH_TOP_GPA: usize = 0x0000_000f_ffff_bfff;

pub const IO_PAGE_GVA: u64 = 0x0000_ffff_ffff_e000;
pub const IO_PAGE_GPA: u64 = 0x0000_000f_ffff_f000;
Expand Down
7 changes: 7 additions & 0 deletions src/hyperlight_common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@ pub mod version_note;

/// cbindgen:ignore
pub mod virtq;

/// cbindgen:ignore
pub mod arch {
#[cfg(target_arch = "aarch64")]
#[path = "aarch64/exn.rs"]
pub mod exn;
}
4 changes: 0 additions & 4 deletions src/hyperlight_common/src/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

pub const PAGE_SHIFT: u64 = 12;
pub const PAGE_SIZE: u64 = 1 << 12;
pub const PAGE_SIZE_USIZE: usize = 1 << 12;

/// A memory region in the guest address space
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(C)]
Expand Down
Loading
Loading