Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4f79454
nix: Support developing on macOS
syntactically Jul 20, 2026
dfaccfa
Reduce duplication of interrupt handle state machines
syntactically Jul 6, 2026
7c99038
Abstract out interrupt handle retry logic
syntactically Jul 20, 2026
03fdbdd
Be more careful about cfg(target_os = "linux") vs cfg(unix)
syntactically Jul 6, 2026
9fd78b0
hvf: add cfg items and detection stub
syntactically Jul 6, 2026
dc84b0c
hvf: add Rust bindings
syntactically Jul 6, 2026
4cced20
hvf: add interrupt handle using `hv_vcpus_exit`
syntactically Jul 6, 2026
b5ec3f6
Disentangle host and guest page sizes
syntactically Jul 7, 2026
5b5ae86
Change guest layout to support 16k host pages
syntactically Jul 15, 2026
8b97046
Make VirtualMachine::set_{regs,sregs,fpu} take &mut
syntactically Jul 8, 2026
f5a27f4
[tests] hvf: support identifiers and reduce thread counts
syntactically Jul 20, 2026
a81433e
Restrict usage of MIDR_EL1 to Linux
syntactically Jul 20, 2026
7a6e2fd
Initial single-address-space support for Hypervisor.framework
syntactically Jul 20, 2026
e39d267
cargo: Add codesigning runner script for MacOS
syntactically Jul 20, 2026
cac4dc7
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
35f5830
aarch64: Move machinery for decoding ESR_ELx to hyperlight-common
syntactically Aug 1, 2026
1324b1a
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
9a412e3
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
0600270
fixup! Abstract out interrupt handle retry logic
syntactically Aug 1, 2026
6ac5585
fixup! Reduce duplication of interrupt handle state machines
syntactically Aug 1, 2026
91e4b98
fixup! Disentangle host and guest page sizes
syntactically Aug 1, 2026
1ac40f8
fixup! hvf: add Rust bindings
syntactically Aug 1, 2026
9f409ec
ci: enable running on MacOS/HVF
syntactically Aug 1, 2026
5663bfb
fixup! hvf: add Rust bindings
syntactically Aug 1, 2026
fa1367f
fixup! Initial single-address-space support for Hypervisor.framework
syntactically Aug 1, 2026
42993eb
fixup! Disentangle host and guest page sizes
syntactically Aug 1, 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
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 @@ -13,6 +13,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
resets to a clean default. On KVM the guest may only read or write declared
MSRs, on MSHV and WHP this is not enforced. by @ludfjig in https://github.com/hyperlight-dev/hyperlight/pull/991

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.

### 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.

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
105 changes: 105 additions & 0 deletions src/hyperlight_common/src/arch/aarch64/exn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
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.
*/

/// Utility function to extract an (inclusive on both ends) bit range
/// from a quadword.
#[inline(always)]
fn bits<const HIGH_BIT: u8, const LOW_BIT: u8>(x: u64) -> u64 {
(x & ((1 << (HIGH_BIT + 1)) - 1)) >> LOW_BIT
}

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