Skip to content
Draft
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: 1 addition & 1 deletion src/hyperlight_host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ tracing-core = "0.1.36"
tracing-opentelemetry = { version = "0.33.0", optional = true }
hyperlight-common = { workspace = true, default-features = true, features = [ "std" ] }
hyperlight-guest-tracing = { workspace = true, default-features = true, optional = true }
vmm-sys-util = "0.15.0"
crossbeam-channel = "0.5.15"
thiserror = "2.0.18"
chrono = { version = "0.4", optional = true }
Expand Down Expand Up @@ -83,6 +82,7 @@ kvm-bindings = { version = "0.14", features = ["fam-wrappers"], optional = true
kvm-ioctls = { version = "0.25", optional = true }
mshv-bindings = { version = "0.6", optional = true }
mshv-ioctls = { version = "0.6", optional = true}
vmm-sys-util = "0.15.0"

[dev-dependencies]
uuid = { version = "1.23.3", features = ["v4"] }
Expand Down
27 changes: 23 additions & 4 deletions src/hyperlight_host/src/hypervisor/hyperlight_vm/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ limitations under the License.
// TODO(aarch64): implement arch-specific HyperlightVm methods

use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64};
use std::sync::atomic::AtomicU8;
#[cfg(target_os = "linux")]
use std::sync::atomic::{AtomicBool, AtomicU64};

use super::{
AccessPageTableError, CreateHyperlightVmError, DispatchGuestCallError, HyperlightVm,
Expand All @@ -29,12 +31,17 @@ use crate::hypervisor::hyperlight_vm::get_guest_log_filter;
use crate::hypervisor::regs::{CommonFpu, CommonRegisters, CommonSpecialRegisters};
#[cfg(kvm)]
use crate::hypervisor::virtual_machine::kvm::KvmVm;
#[cfg(kvm)]
#[cfg(target_os = "windows")]
use crate::hypervisor::virtual_machine::whp::WhpVm;
#[cfg(any(kvm, mshv3, target_os = "windows"))]
use crate::hypervisor::virtual_machine::{HypervisorType, VmError};
use crate::hypervisor::virtual_machine::{
RegisterError, ResetVcpuError, VirtualMachine, get_available_hypervisor,
};
#[cfg(target_os = "linux")]
use crate::hypervisor::{InterruptHandleImpl, LinuxInterruptHandle};
#[cfg(target_os = "windows")]
use crate::hypervisor::{InterruptHandleImpl, PartitionState, WindowsInterruptHandle};
use crate::mem::mgr::{SandboxMemoryManager, SnapshotSharedMemory};
use crate::mem::shared_mem::{GuestSharedMemory, HostSharedMemory};
use crate::sandbox::SandboxConfiguration;
Expand All @@ -54,7 +61,7 @@ impl HyperlightVm {
next_action: NextAction,
rsp_gva: u64,
page_size: usize,
config: &SandboxConfiguration,
#[cfg_attr(target_os = "windows", allow(unused_variables))] config: &SandboxConfiguration,
#[cfg(gdb)] _gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>,
#[cfg(crashdump)] _rt_cfg: SandboxRuntimeConfig,
#[cfg(feature = "mem_profile")] _trace_info: MemTraceInfo,
Expand All @@ -64,13 +71,16 @@ impl HyperlightVm {
let 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(target_os = "windows")]
Some(HypervisorType::Whp) => Box::new(WhpVm::new().map_err(VmError::CreateVm)?),
None => return Err(CreateHyperlightVmError::NoHypervisorFound),
};
vm.set_sregs(&CommonSpecialRegisters::defaults(root_pt_addr))
.map_err(VmError::Register)?;

#[cfg(target_os = "linux")]
let interrupt_handle: Arc<dyn InterruptHandleImpl> = Arc::new(LinuxInterruptHandle {
state: AtomicU8::new(0),
tid: AtomicU64::new(unsafe { libc::pthread_self() as u64 }),
Expand All @@ -79,6 +89,15 @@ impl HyperlightVm {
dropped: AtomicBool::new(false),
});

#[cfg(target_os = "windows")]
let interrupt_handle: Arc<dyn InterruptHandleImpl> = Arc::new(WindowsInterruptHandle {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just a heads up that there is a big refactor/simplification to the interrupt handle machinery in #1674 that you may want to take a look at.

state: AtomicU8::new(0),
partition_state: std::sync::RwLock::new(PartitionState {
handle: vm.partition_handle(),
dropped: false,
}),
});

let snapshot_slot = 0u32;
let scratch_slot = 1u32;
let vm_can_reset_vcpu = vm.can_reset_vcpu();
Expand Down
22 changes: 20 additions & 2 deletions src/hyperlight_host/src/hypervisor/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,31 @@ pub(crate) use x86_64::*;

#[cfg(target_arch = "aarch64")]
mod aarch64;
#[cfg(target_os = "windows")]
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
use std::collections::HashSet;

#[cfg(target_os = "windows")]
use windows::Win32::System::Hypervisor::WHV_REGISTER_VALUE;

/// The Windows SDK requires 16-byte alignment for `WHV_REGISTER_VALUE`.
#[cfg(target_os = "windows")]
#[repr(C, align(16))]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub(crate) struct Align16<T>(pub(crate) T);

#[cfg(target_os = "windows")]
const _: () = {
assert!(
std::mem::size_of::<Align16<WHV_REGISTER_VALUE>>()
== std::mem::size_of::<WHV_REGISTER_VALUE>()
);
assert!(std::mem::align_of::<Align16<WHV_REGISTER_VALUE>>() == 16);
};

#[cfg(target_arch = "aarch64")]
pub(crate) use aarch64::*;

#[cfg(target_os = "windows")]
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
#[derive(Debug, PartialEq)]
pub(crate) enum FromWhpRegisterError {
MissingRegister(HashSet<i32>),
Expand Down
2 changes: 2 additions & 0 deletions src/hyperlight_host/src/hypervisor/regs/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ pub(crate) struct CommonDebugRegs {

#[cfg(kvm)]
pub(crate) mod kvm_reg;
#[cfg(windows)]
pub(crate) mod whp_reg;
128 changes: 128 additions & 0 deletions src/hyperlight_host/src/hypervisor/regs/aarch64/whp_reg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
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 windows::Win32::System::Hypervisor::WHV_REGISTER_NAME;

const X0: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0002_0000);
const Q0: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0003_0000);

pub(crate) const WHV_ARM64_REGISTER_PC: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0002_0022);
pub(crate) const WHV_ARM64_REGISTER_PSTATE: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0002_0023);
pub(crate) const WHV_ARM64_REGISTER_SP_EL0: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0002_0020);
pub(crate) const WHV_ARM64_REGISTER_SP_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0002_0021);

pub(crate) const WHV_ARM64_REGISTER_SCTLR_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_0002);
pub(crate) const WHV_ARM64_REGISTER_CPACR_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_0004);
pub(crate) const WHV_ARM64_REGISTER_TTBR0_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_0005);
pub(crate) const WHV_ARM64_REGISTER_TCR_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_0007);
pub(crate) const WHV_ARM64_REGISTER_MAIR_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_000b);
pub(crate) const WHV_ARM64_REGISTER_VBAR_EL1: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_000c);
pub(crate) const WHV_ARM64_REGISTER_FPCR: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_0012);
pub(crate) const WHV_ARM64_REGISTER_FPSR: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x0004_0013);

pub(crate) const GP_REGISTER_NAMES: [WHV_REGISTER_NAME; 34] = [
xreg(0),
xreg(1),
xreg(2),
xreg(3),
xreg(4),
xreg(5),
xreg(6),
xreg(7),
xreg(8),
xreg(9),
xreg(10),
xreg(11),
xreg(12),
xreg(13),
xreg(14),
xreg(15),
xreg(16),
xreg(17),
xreg(18),
xreg(19),
xreg(20),
xreg(21),
xreg(22),
xreg(23),
xreg(24),
xreg(25),
xreg(26),
xreg(27),
xreg(28),
xreg(29),
xreg(30),
WHV_ARM64_REGISTER_PC,
WHV_ARM64_REGISTER_SP_EL0,
WHV_ARM64_REGISTER_PSTATE,
];

pub(crate) const FP_REGISTER_NAMES: [WHV_REGISTER_NAME; 34] = [
qreg(0),
qreg(1),
qreg(2),
qreg(3),
qreg(4),
qreg(5),
qreg(6),
qreg(7),
qreg(8),
qreg(9),
qreg(10),
qreg(11),
qreg(12),
qreg(13),
qreg(14),
qreg(15),
qreg(16),
qreg(17),
qreg(18),
qreg(19),
qreg(20),
qreg(21),
qreg(22),
qreg(23),
qreg(24),
qreg(25),
qreg(26),
qreg(27),
qreg(28),
qreg(29),
qreg(30),
qreg(31),
WHV_ARM64_REGISTER_FPSR,
WHV_ARM64_REGISTER_FPCR,
];

pub(crate) const SPECIAL_REGISTER_NAMES: [WHV_REGISTER_NAME; 7] = [
WHV_ARM64_REGISTER_TTBR0_EL1,
WHV_ARM64_REGISTER_TCR_EL1,
WHV_ARM64_REGISTER_MAIR_EL1,
WHV_ARM64_REGISTER_SCTLR_EL1,
WHV_ARM64_REGISTER_CPACR_EL1,
WHV_ARM64_REGISTER_VBAR_EL1,
WHV_ARM64_REGISTER_SP_EL1,
];

pub(crate) const fn xreg(index: u32) -> WHV_REGISTER_NAME {
assert!(index < 31);
WHV_REGISTER_NAME(X0.0 + index as i32)
}

pub(crate) const fn qreg(index: u32) -> WHV_REGISTER_NAME {
assert!(index < 32);
WHV_REGISTER_NAME(Q0.0 + index as i32)
}
2 changes: 1 addition & 1 deletion src/hyperlight_host/src/hypervisor/regs/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ pub(crate) use special_regs::*;
pub(crate) use standard_regs::*;

#[cfg(target_os = "windows")]
pub(crate) use super::FromWhpRegisterError;
pub(crate) use super::{Align16, FromWhpRegisterError};
17 changes: 1 addition & 16 deletions src/hyperlight_host/src/hypervisor/regs/x86_64/special_regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use serde::{Deserialize, Serialize};
use windows::Win32::System::Hypervisor::*;

#[cfg(target_os = "windows")]
use super::FromWhpRegisterError;
use super::{Align16, FromWhpRegisterError};

// CR0 bits used by both 32-bit and 64-bit guest
const CR0_PE: u64 = 1;
Expand Down Expand Up @@ -217,21 +217,6 @@ impl From<&CommonSpecialRegisters> for kvm_sregs {
}
}

/// WHV_REGISTER_VALUE must be 16-byte aligned, but the rust struct is incorrectly generated
/// as 8-byte aligned. This is a workaround to ensure that the struct is 16-byte aligned.
#[cfg(target_os = "windows")]
#[repr(C, align(16))]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub(crate) struct Align16<T>(pub(crate) T);

#[cfg(target_os = "windows")]
const _: () = {
assert!(
std::mem::size_of::<Align16<WHV_REGISTER_VALUE>>()
== std::mem::size_of::<WHV_REGISTER_VALUE>()
);
};

#[cfg(target_os = "windows")]
pub(crate) const WHP_SREGS_NAMES_LEN: usize = 17;
#[cfg(target_os = "windows")]
Expand Down
Loading
Loading