Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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"
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Changed

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
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
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
8 changes: 6 additions & 2 deletions src/hyperlight_host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ oci-spec = { version = "0.10", default-features = false, features = ["image"] }
sha2 = "0.11"
hex = "0.4"
tempfile = "3.27.0"
parking_lot = "0.12.5"

[target.'cfg(windows)'.dependencies]
windows = { version = "0.62", features = [
Expand All @@ -78,7 +79,7 @@ rust-embed = { version = "8.11.0", features = ["debug-embed", "include-exclude",
windows-version = "0.1"
lazy_static = "1.4.0"

[target.'cfg(unix)'.dependencies]
[target.'cfg(target_os = "linux")'.dependencies]
kvm-bindings = { version = "0.14", features = ["fam-wrappers"], optional = true }
kvm-ioctls = { version = "0.25", optional = true }
mshv-bindings = { version = "0.6", optional = true }
Expand Down Expand Up @@ -123,9 +124,11 @@ proc-maps = "0.5.0"
anyhow = { version = "1.0.102" }
cfg_aliases = "0.2.1"
built = { version = "0.8.1", optional = true, features = ["chrono", "git2"] }
bindgen = { version = "0.72", features = ["prettyplease"] }
cc = "1.2"

[features]
default = ["kvm", "mshv3", "build-metadata"]
default = ["kvm", "mshv3", "hvf", "build-metadata"]
function_call_metrics = []
executable_heap = []
# This feature enables printing of debug information to stdout in debug builds
Expand All @@ -136,6 +139,7 @@ trace_guest = ["dep:opentelemetry", "dep:tracing-opentelemetry", "dep:hyperlight
mem_profile = [ "trace_guest", "dep:framehop", "dep:fallible-iterator", "hyperlight-common/mem_profile" ]
kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"]
mshv3 = ["dep:mshv-bindings", "dep:mshv-ioctls"]
hvf = []
hw-interrupts = []
# This enables easy debug in the guest
gdb = ["dep:gdbstub", "dep:gdbstub_arch"]
Expand Down
60 changes: 56 additions & 4 deletions src/hyperlight_host/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

use anyhow::Result;
use anyhow::{Context, Result};
#[cfg(feature = "build-metadata")]
use built::write_built_file;

fn main() -> Result<()> {
// re-run the build if this script is changed (or deleted!),
// even if the rust code is completely unchanged.
println!("cargo:rerun-if-changed=build.rs");
let out_dir = std::env::var("OUT_DIR")?;
let out_path = std::path::PathBuf::from(&out_dir);
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?;

// Windows requires the hyperlight_surrogate.exe binary to be next to the executable running
// hyperlight. We are using rust-embed to include the binary in the hyperlight-host library
Expand All @@ -41,9 +44,7 @@ fn main() -> Result<()> {
// We need to copy/rename the source for hyperlight surrogate into a
// temp directory because we cannot include a file name `Cargo.toml`
// inside this package.
let out_dir = std::env::var("OUT_DIR")?;
std::fs::create_dir_all(format!("{out_dir}/hyperlight_surrogate/src"))?;
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?;
std::fs::copy(
format!("{manifest_dir}/src/hyperlight_surrogate/src/main.rs"),
format!("{out_dir}/hyperlight_surrogate/src/main.rs"),
Expand All @@ -62,7 +63,7 @@ fn main() -> Result<()> {
// be the same as the CARGO_TARGET_DIR for the hyperlight-host otherwise
// the build script will hang. Using a sub directory works tho!
// xref - https://github.com/rust-lang/cargo/issues/6412
let target_dir = std::path::PathBuf::from(&out_dir).join("../../hls");
let target_dir = out_path.join("../../hls");

let profile = std::env::var("PROFILE")?;
let build_profile = if profile.to_lowercase() == "debug" {
Expand Down Expand Up @@ -101,13 +102,64 @@ fn main() -> Result<()> {
);
}

if std::env::var("CARGO_CFG_TARGET_OS")? == "macos"
&& std::env::var("CARGO_FEATURE_HVF").is_ok()
{
println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS");
println!(
"cargo:rerun-if-changed=src/hyperlight_host/src/hypervisor/virtual_machine/hvf/bindings.h"
);
println!(
"cargo:rerun-if-changed=src/hyperlight_host/src/hypervisor/virtual_machine/hvf/fp_abi.c"
);
println!("cargo:rustc-link-lib=framework=Hypervisor");
bindgen::Builder::default()
.clang_args(&["-framework", "Hypervisor"])
.clang_args(&[
"-I",
&format!("{manifest_dir}/src/hypervisor/virtual_machine/hvf"),
])
// The hvf simd register functions use C simd vector
// parameters/returns for the register value, which Rust
// does not presently stably support for `extern "C"`
// code. So, we don't generate native bindings for these
// functions, and instead generate C stubs (see `fp_abi.c`,
// which is built below)
.blocklist_type("hv_simd_fp_uchar16_t")
.blocklist_function("hv_vcpu_get_simd_fp_reg")
.blocklist_function("hv_vcpu_set_simd_fp_reg")
.default_alias_style(bindgen::AliasVariation::NewType)
.type_alias("hv_memory_flags_t")
.newtype_enum("hv_reg_t")
.newtype_enum("hv_simd_fp_reg_t")
.newtype_enum("hv_sys_reg_t")
.newtype_enum("hv_exit_reason_t")
.no_debug("hv_return_t")
.formatter(bindgen::Formatter::Prettyplease)
.header(format!(
"{manifest_dir}/src/hypervisor/virtual_machine/hvf/bindings.h"
))
.generate()
.context("Unable to generate hvf bindings")?
.write_to_file(out_path.join("hvf_bindings.rs"))
.context("Couldn't write hvf bindings")?;

cc::Build::new()
.opt_level(3)
.file(format!(
"{manifest_dir}/src/hypervisor/virtual_machine/hvf/fp_abi.c"
))
.compile("hyperlight_host_hvf_abi_wrapper");
}

// Makes #[cfg(kvm)] == #[cfg(all(feature = "kvm", target_os = "linux"))]
// Essentially the kvm and mshv3 features are ignored on windows as long as you use #[cfg(kvm)] and not #[cfg(feature = "kvm")].
// You should never use #[cfg(feature = "kvm")] or #[cfg(feature = "mshv3")] in the codebase.
cfg_aliases::cfg_aliases! {
gdb: { all(feature = "gdb", debug_assertions, target_arch = "x86_64") },
kvm: { all(feature = "kvm", target_os = "linux") },
mshv3: { all(feature = "mshv3", target_os = "linux") },
hvf: { all(feature = "hvf", target_os = "macos") },
crashdump: { all(feature = "crashdump", target_arch = "x86_64") },
// print_debug feature is aliased with debug_assertions to make it only available in debug-builds.
print_debug: { all(feature = "print_debug", debug_assertions) },
Expand Down
34 changes: 21 additions & 13 deletions src/hyperlight_host/src/hypervisor/hyperlight_vm/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,28 @@ limitations under the License.
// TODO(aarch64): implement arch-specific HyperlightVm methods

use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64};

use super::{
AccessPageTableError, CreateHyperlightVmError, DispatchGuestCallError, HyperlightVm,
InitializeError,
};
#[cfg(hvf)]
use crate::hypervisor::HvfInterruptHandle;
use crate::hypervisor::InterruptHandleImpl;
#[cfg(any(kvm, mshv3))]
use crate::hypervisor::LinuxInterruptHandle;
#[cfg(gdb)]
use crate::hypervisor::gdb::{DebugCommChannel, DebugMsg, DebugResponse};
use crate::hypervisor::hyperlight_vm::get_guest_log_filter;
use crate::hypervisor::regs::{CommonFpu, CommonRegisters, CommonSpecialRegisters};
#[cfg(hvf)]
use crate::hypervisor::virtual_machine::hvf::HvfVm;
#[cfg(kvm)]
use crate::hypervisor::virtual_machine::kvm::KvmVm;
#[cfg(kvm)]
use crate::hypervisor::virtual_machine::{HypervisorType, VmError};
use crate::hypervisor::virtual_machine::{
RegisterError, ResetVcpuError, VirtualMachine, get_available_hypervisor,
HypervisorType, RegisterError, ResetVcpuError, VirtualMachine, VmError,
get_available_hypervisor,
};
use crate::hypervisor::{InterruptHandleImpl, LinuxInterruptHandle};
use crate::mem::mgr::{SandboxMemoryManager, SnapshotSharedMemory};
use crate::mem::shared_mem::{GuestSharedMemory, HostSharedMemory};
use crate::sandbox::SandboxConfiguration;
Expand All @@ -47,6 +51,7 @@ use crate::sandbox::uninitialized::SandboxRuntimeConfig;

impl HyperlightVm {
#[allow(clippy::too_many_arguments)]
#[cfg_attr(target_os = "macos", allow(unused))]
pub(crate) fn new(
snapshot_mem: SnapshotSharedMemory<GuestSharedMemory>,
scratch_mem: GuestSharedMemory,
Expand All @@ -61,23 +66,26 @@ impl HyperlightVm {
) -> std::result::Result<Self, CreateHyperlightVmError> {
// TODO: support gdb on aarch64
type VmType = Box<dyn VirtualMachine>;
let vm: VmType = match get_available_hypervisor() {
#[cfg(hvf)]
let interrupt_handle: Arc<dyn InterruptHandleImpl> =
Arc::new(HvfInterruptHandle::new(config.get_interrupt_retry_delay()));
let mut vm: VmType = match get_available_hypervisor() {
#[cfg(kvm)]
Some(HypervisorType::Kvm) => Box::new(KvmVm::new().map_err(VmError::CreateVm)?),
// TODO: mshv support
#[cfg(mshv3)]
Some(HypervisorType::Mshv) => return Err(CreateHyperlightVmError::NoHypervisorFound),
#[cfg(hvf)]
Some(HypervisorType::Hvf) => {
Box::new(HvfVm::new(interrupt_handle.clone()).map_err(VmError::CreateVm)?)
}
None => return Err(CreateHyperlightVmError::NoHypervisorFound),
};
vm.set_sregs(&CommonSpecialRegisters::defaults(root_pt_addr))
.map_err(VmError::Register)?;
let interrupt_handle: Arc<dyn InterruptHandleImpl> = Arc::new(LinuxInterruptHandle {
state: AtomicU8::new(0),
tid: AtomicU64::new(unsafe { libc::pthread_self() as u64 }),
retry_delay: config.get_interrupt_retry_delay(),
sig_rt_min_offset: config.get_interrupt_vcpu_sigrtmin_offset(),
dropped: AtomicBool::new(false),
});
#[cfg(any(kvm, mshv3))]
let interrupt_handle: Arc<dyn InterruptHandleImpl> =
Arc::new(LinuxInterruptHandle::new(config));

let snapshot_slot = 0u32;
let scratch_slot = 1u32;
Expand Down
Loading
Loading