Skip to content

feat(aarch64): add WHP backend for ARM64 Windows - #1638

Draft
cshung wants to merge 6 commits into
hyperlight-dev:mainfrom
cshung:cshung/whp-aarch64
Draft

feat(aarch64): add WHP backend for ARM64 Windows#1638
cshung wants to merge 6 commits into
hyperlight-dev:mainfrom
cshung:cshung/whp-aarch64

Conversation

@cshung

@cshung cshung commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the WHP (Windows Hypervisor Platform) hypervisor backend for aarch64, enabling hyperlight to run micro-VMs on Windows ARM64 systems.

Resolves #1544

Changes

Structural

  • Restructure whp.rs into whp/ directory (mod.rs + x86_64.rs) to support per-architecture implementations, matching the existing kvm/ and mshv/ pattern
  • Fix super::x86_64::hw_interrupts module path after directory restructure

New: whp/aarch64.rs

  • Manual FFI bindings for ARM64 WHP register names, exit reasons, and exit context layout (extracted from Windows SDK WinHvPlatformDefs.h)
  • Full VirtualMachine trait implementation with:
    • MMIO-based I/O handling (ARM64 has no IO ports)
    • Register get/set via WHvGet/SetVirtualProcessorRegisters
    • Surrogate process support (same pattern as x86_64)

Integration

  • Wire WhpVm into hyperlight_vm/aarch64.rs for Windows platform
  • Add WindowsInterruptHandle for aarch64 Windows
  • Add CpuVendor::current() for aarch64 Windows target

Cross-compilation fix

  • Move vmm-sys-util to unix-only dependencies (it doesn't compile on Windows)

Verification

Verified compilation on three targets:

  • x86_64-pc-windows-msvc (native) — just clippy debug/release pass
  • aarch64-pc-windows-msvc (cross-compile) — cargo check passes
  • aarch64-unknown-linux-gnu (cross-compile) — cargo check --features kvm passes

Note: No runtime testing was possible — requires actual ARM64 Windows hardware with Hyper-V enabled. CI has no ARM64 Windows runners.

Why manual FFI bindings?

The windows crate (v0.62) does not expose ARM64 WHP types (register names, exit reasons, exit context structs). All definitions were extracted from the Windows SDK header WinHvPlatformDefs.h (SDK 10.0.26100.0) which has full ARM64 support behind #ifdef _ARM64_.

Copilot AI review requested due to automatic review settings July 12, 2026 15:02
@cshung cshung added kind/enhancement For PRs adding features, improving functionality, docs, tests, etc. ready-for-review PR is ready for (re-)review labels Jul 12, 2026

Copilot AI left a comment

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.

Pull request overview

Adds a Windows Hypervisor Platform (WHP) backend for Windows/aarch64 so Hyperlight can run micro-VMs on ARM64 Windows systems, aligning WHP’s structure with existing per-arch hypervisor layouts.

Changes:

  • Introduces whp/aarch64.rs implementing the VirtualMachine trait for ARM64 WHP, including MMIO-based exit handling and register get/set via WHvGet/SetVirtualProcessorRegisters.
  • Restructures the WHP backend into whp/ with per-architecture modules and fixes x86_64 interrupt helper module paths.
  • Wires WHP into the aarch64 Hyperlight VM path on Windows and moves vmm-sys-util into unix-only dependencies to fix Windows builds.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/hyperlight_host/src/sandbox/snapshot/file/config.rs Adds Windows/aarch64 CPU vendor token for snapshot config.
src/hyperlight_host/src/hypervisor/virtual_machine/whp/x86_64.rs Updates hw_interrupts module paths after WHP directory restructure.
src/hyperlight_host/src/hypervisor/virtual_machine/whp/mod.rs New per-arch WHP module dispatcher (x86_64 vs aarch64).
src/hyperlight_host/src/hypervisor/virtual_machine/whp/aarch64.rs New ARM64 WHP backend implementation and manual ARM64 WHP FFI bindings.
src/hyperlight_host/src/hypervisor/hyperlight_vm/aarch64.rs Selects WHP on Windows/aarch64 and adds Windows interrupt handle wiring.
src/hyperlight_host/Cargo.toml Makes vmm-sys-util unix-only to avoid Windows compilation failures.

Comment thread src/hyperlight_host/src/hypervisor/virtual_machine/whp/aarch64.rs Outdated
Comment thread src/hyperlight_host/src/hypervisor/virtual_machine/whp/aarch64.rs Outdated
Comment thread src/hyperlight_host/src/hypervisor/virtual_machine/whp/aarch64.rs
Comment thread src/hyperlight_host/src/hypervisor/virtual_machine/whp/aarch64.rs Outdated
Comment thread src/hyperlight_host/src/sandbox/snapshot/file/config.rs Outdated
@cshung
cshung marked this pull request as draft July 13, 2026 02:13
@github-actions github-actions Bot removed the ready-for-review PR is ready for (re-)review label Jul 13, 2026
Comment thread src/hyperlight_host/src/sandbox/snapshot/file/config.rs Outdated
cshung and others added 3 commits July 30, 2026 22:13
Implement the WHP hypervisor backend for aarch64 Windows, enabling
hyperlight to run micro-VMs on Windows ARM64 systems.

Changes:
- Restructure whp.rs into whp/ directory (whp/mod.rs + whp/x86_64.rs)
  to support per-architecture implementations (matching kvm/mshv pattern)
- Add whp/aarch64.rs with full VirtualMachine trait implementation:
  - Manual FFI bindings for ARM64 WHP register names, exit reasons, and
    exit context layout (from Windows SDK WinHvPlatformDefs.h)
  - Run loop handling MMIO-based I/O (ARM64 has no IO ports)
  - Register get/set via WHvGet/SetVirtualProcessorRegisters
  - Surrogate process support (same pattern as x86_64)
- Wire WhpVm into hyperlight_vm/aarch64.rs for Windows platform
- Fix super::x86_64::hw_interrupts path after directory restructure

Resolves: hyperlight-dev#1544

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6f20a05d-6bee-4e2e-b320-12f8d9759bbc
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
- Move vmm-sys-util to unix-only dependencies (it doesn't compile on Windows)
- Fix WHV_UINT128 field access (requires Anonymous wrapper on windows crate)
- Add CpuVendor::current() for aarch64 Windows target
- Remove redundant partition_handle inherent method and unused cancelled field
- Fix unused import warnings
- Add #[allow(dead_code)] on exit reason constants module

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6f20a05d-6bee-4e2e-b320-12f8d9759bbc
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
@cshung
cshung force-pushed the cshung/whp-aarch64 branch from 5f992dc to 1d3a299 Compare July 30, 2026 22:14
cshung and others added 3 commits July 30, 2026 22:17
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
Preserve FPU register errors, use safe DLL lookup, and document the Windows snapshot token accurately.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
@cshung

cshung commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

End-to-end cargo-hyperlight validation completed on the ARM64 WHP hardware.

Using this PR's 0.16 crates, a freshly scaffolded sample successfully built aarch64-hyperlight-none guests and ran through WHP in debug and release. Host callbacks, typed calls, persistent state, snapshot, and restore passed. I also ran the release workflow 10 times with surrogate mappings and 10 times with surrogates disabled. All runs produced the expected output.

The backend works. The published scaffold is the remaining user-experience gap: cargo-hyperlight pins Hyperlight 0.15 and hardcodes the generated host's x64 guest path. Filed hyperlight-dev/cargo-hyperlight#70 with the reproduction and results.

@syntactically syntactically left a comment

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.

This looks great! I have a bunch of little nits, and also I (more majorly) think that the addition of reset_vcpu to InteruptHandle seems wrong.

// TODO: mshv support
#[cfg(mshv3)]
Some(HypervisorType::Mshv) => return Err(CreateHyperlightVmError::NoHypervisorFound),
Some(HypervisorType::Mshv) => {

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.

This line looks like it's the same before/after?

});

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

"No fallback path for vcpu reset on aarch64"
);
self.vm.reset_vcpu()?;
self.interrupt_handle.reset_vcpu(self.vm.as_mut())?;

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.

What's this change about? It seems like the wrong place for this.

If it's related to the locking that happens in the interrupt handle: that's required because the interrupt handle can outlive the WhpVm object that it is created from (and the partition is destroyed when the latter is dropped). Here, you have a reference to the WhpVm on hand, so you can be sure that it hasn't been dropped (and then destroyed).

//! This module provides the [`VirtualMachine`] trait implementation using the
//! WHP APIs on Windows ARM64 systems. Because the `windows` crate does not yet
//! expose ARM64 WHP structures, we define our own FFI bindings derived from
//! the Windows SDK header `WinHvPlatformDefs.h` (10.0.26100.0).

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.

Is there an issue on the upstream windows crate about getting these exposed?

Also, I remember that Windows APIs in general often have a bunch of random aligned(16) or similar things---are those accounted for here? I remember that the bindgen that the windows crate uses used to get that wrong.

WHV_PARTITION_PROPERTY_CODE(0x00001012);
const WHV_ARM64_REGISTER_GICR_BASE_GPA: WHV_REGISTER_NAME = WHV_REGISTER_NAME(0x00063000);

#[repr(C)]

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.

Ouch, is it really a hard requirement from WHP to have the interrupt controller configured? I think I have done some experiments with mshv on Linux in the past and had success without an ic.

}
}

// ============================================================================

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.

This can also perhaps be shared with the x86_64 variant?

}
} else if let Some(val) = super::x86_64::hw_interrupts::handle_io_in(port) {
} else if let Some(val) =
crate::hypervisor::virtual_machine::x86_64::hw_interrupts::handle_io_in(

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.

Perhaps use crate::hypervisor::virtual_machine::x86_64 or something to reduce the formatting churn?

fn clear_cancel(&self);

/// Reset the vCPU while honoring platform lifecycle synchronization.
#[cfg(target_arch = "aarch64")]

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.

As mentioned above, this seems like the wrong place for this.

use std::thread;

// We have a high thread count to stress test and to have interesting interleavings
// ARM64 WHP partitions include GICv3 state, limiting practical partition

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.

Can you elaborate on this a little bit?

use tracing::{error, trace};

#[cfg(target_arch = "aarch64")]
const POOL_SIZE: usize = 64;

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.

Are you planning to run the tests in single-threaded mode in CI? I initially had a similar change in #1674, but I found that CI ran multiple tests at once and went past thread limits, so I changed that code to work correctly (if slowly) with any amount of concurrency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/enhancement For PRs adding features, improving functionality, docs, tests, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support AArch64 on Windows

3 participants