Skip to content

feat(aarch64): add GDB debugging for Windows ARM64 WHP - #1907

Open
cshung wants to merge 2 commits into
hyperlight-dev:mainfrom
cshung:cshung/whp-aarch64-gdb
Open

cshung wants to merge 2 commits into
hyperlight-dev:mainfrom
cshung:cshung/whp-aarch64-gdb

Conversation

@cshung

@cshung cshung commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GDB stub support for guests running on the ARM64 WHP backend.

Changes

Debug core

  • Split the x86_64 debug code out of hyperlight_vm/x86_64.rs into a shared hyperlight_vm/debug.rs.
  • Rename gdb/x86_64_target.rs to gdb/target.rs and add per-architecture register handling in gdb/arch/.
  • Give DebuggableVm default methods so backends without hardware breakpoints or single step report Unsupported.

ARM64 WHP

  • Implement DebuggableVm for the aarch64 WHP VM, using the batched register helpers.
  • Flush the host instruction cache after guest memory writes so software breakpoints take effect.

Docs

  • Document ARM64 debugging in docs/how-to-debug-a-hyperlight-guest.md and CHANGELOG.md.

Verification

On Windows ARM64 (WHP):

  • just build, just clippy, just guests, just test and just fmt-check pass.

@cshung cshung added the kind/enhancement For PRs adding features, improving functionality, docs, tests, etc. label Oct 8, 2026
@hyperlight-gh-bot

This comment has been minimized.

@cshung
cshung marked this pull request as ready for review October 8, 2026 19:33
Copilot AI balanced review requested due to automatic review settings October 8, 2026 19:33

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.

🟡 Changes recommended

Breakpoint state can survive crash or cancellation recovery, and the hidden cache-sync mapping conflicts with the public mapping contract.

4 open findings
What changed in this PR

Adds Windows ARM64 WHP guest debugging and generalizes the GDB implementation across architectures.

Changes:

  • Adds ARM64 registers, software breakpoints, stepping, and cache synchronization.
  • Extracts shared debugger logic from x86_64 code.
  • Updates tests, documentation, and platform configuration.
File Description
CHANGELOG.md Records ARM64 GDB support.
docs/​how-to-debug-a-hyperlight-guest.md Documents architecture-specific capabilities.
src/​hyperlight_host/​build.rs Enables GDB on Windows ARM64.
src/​hyperlight_host/​examples/​guest-debugging/​main.rs Adds ARM64 debugging tests.
src/​hyperlight_host/​src/​hypervisor/​gdb/​arch.rs Dispatches architecture-specific logic.
src/​hyperlight_host/​src/​hypervisor/​gdb/​arch/​aarch64.rs Implements ARM64 breakpoint and step decoding.
src/​hyperlight_host/​src/​hypervisor/​gdb/​arch/​x86_64.rs Houses extracted x86_64 logic.
src/​hyperlight_host/​src/​hypervisor/​gdb/​event_loop.rs Maps ARM64 stop reasons.
src/​hyperlight_host/​src/​hypervisor/​gdb/​mod.rs Extends shared debugging interfaces.
src/​hyperlight_host/​src/​hypervisor/​gdb/​target.rs Adds architecture-specific GDB registers.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​aarch64.rs Connects GDB to ARM64 VMs.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​debug.rs Centralizes breakpoint and stepping state.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​mod.rs Handles ARM64 debug exits.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​x86_64.rs Removes extracted debugger logic.
src/​hyperlight_host/​src/​hypervisor/​virtual_machine/​mod.rs Extends VM exits and errors.
src/​hyperlight_host/​src/​hypervisor/​virtual_machine/​whp/​aarch64.rs Implements WHP debugging and cache synchronization.
src/​hyperlight_host/​src/​sandbox/​initialized.rs Guards snapshots with active breakpoints.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +101 to +104
DebugMsg::DisableDebug => {
detach = true;
DebugResponse::DisableDebug
}
Comment on lines +795 to +797
#[cfg(target_arch = "aarch64")]
if let Err(e) = self.cancel_pending_software_step(mem_mgr) {
break Err(HandleDebugError::from(e).into());
.copy_from_slice(&DEBUG_CACHE_SYNC_CODE, 0)
.map_err(|e| CreateVmError::InitializeDebug(e.to_string()))?;
let (host_memory, guest_memory) = memory.build();
let region = guest_memory.mapping_at(DEBUG_CACHE_SYNC_GPA, MemoryRegionType::Scratch);
// aligned. However, the ABI requirement is that the stack
// be aligned _before a call instruction_, which means
// that the stack needs to actually be ≡ 8 mod 16 at the
// that the stack needs to actually be ≡ 8 mod 16 at the
cshung and others added 2 commits October 9, 2026 08:38
## Summary

Adds GDB stub support for guests running on the ARM64 WHP backend.

## Changes

### Debug core
* Split the x86_64 debug code out of `hyperlight_vm/x86_64.rs` into a shared `hyperlight_vm/debug.rs`.
* Rename `gdb/x86_64_target.rs` to `gdb/target.rs` and add per-architecture register handling in `gdb/arch/`.
* Give `DebuggableVm` default methods so backends without hardware breakpoints or single step report `Unsupported`.

### ARM64 WHP
* Implement `DebuggableVm` for the aarch64 WHP VM, using the batched register helpers.
* Flush the host instruction cache after guest memory writes so software breakpoints take effect.

### Docs
* Document ARM64 debugging in `docs/how-to-debug-a-hyperlight-guest.md` and `CHANGELOG.md`.

## Verification

On Windows ARM64 (WHP):
* `just build`, `just clippy`, `just guests`, `just test` and `just fmt-check` pass.

---------

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

* Run the full disable path when the debugger detaches after a crash, so software breakpoints and pending steps are cleaned up.
* Cancel pending software steps for any cancellation source, not only debugger interrupts.
* Reject `map_region` requests that overlap the hidden cache sync page at GPA 0x1000, and add a test.
* Restore the `≡` and `×` characters in `hyperlight_vm/x86_64.rs` comments.

## Verification

On Windows ARM64 (WHP):
* `just clippy`, `just fmt-check` and the `hypervisor::` and `map_region` lib tests with the `gdb` feature pass.

---------

Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cshung
cshung force-pushed the cshung/whp-aarch64-gdb branch from 8c0c245 to 39ea4cb Compare October 9, 2026 16:54
@hyperlight-gh-bot

Copy link
Copy Markdown

Benchmark Results

Measured commit: 39ea4cbb9456
Baseline commit: 9f7cfba4d8a5

kvm / amd (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

encode_control decode_vec_bytes_copy
byte_chunks 814.70 ns (➖ 1.04x slower)
vec_bytes 581.64 ns (➖ 1.01x faster)
377.06 µs (➖ 1.00x slower)

payload_allocation

slot_pool_segmented
262144 522.19 ns (➖ 1.01x faster)
65536 143.59 ns (➖ 1.14x faster)

sandboxes

create_initialized_and_drop
medium 82.37 ms (➖ 1.01x faster)

slot_pool

alloc_dealloc_1500 alloc_dealloc_4096 alloc_dealloc_128
7.75 ns (➖ 1.01x faster) 7.72 ns (➖ 1.00x faster) 7.78 ns (➖ 1.01x slower)

snapshot_files

load_snapshot_unverified
small 93.48 µs (➖ 1.01x slower)

virtq_readonly

slot_pool_segmented_fragmented slot_pool_segmented
262144 7.16 µs (➖ 1.01x faster) 7.32 µs (➖ 1.03x slower)
65536 2.05 µs (➖ 1.07x slower) 1.93 µs (➖ 1.09x faster)

virtq_readwrite

slot_pool_segmented_fragmented slot_pool_segmented
65536 6.24 µs (➖ 1.02x faster) 6.20 µs (➖ 1.08x faster)
8192 1.09 µs (➖ 1.05x slower) 1.07 µs (➖ 1.03x slower)
262144 28.34 µs (➖ 1.04x slower)
kvm / intel (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

encode_control decode_vec_bytes_copy
byte_chunks 851.90 ns (➖ 1.03x slower)
vec_bytes 606.16 ns (➖ 1.01x faster)
740.26 µs (➖ 1.01x faster)

payload_allocation

slot_pool_segmented
262144 601.50 ns (➖ 1.12x slower)
65536 162.66 ns (➖ 1.12x slower)

sandboxes

create_initialized_and_drop
medium 85.64 ms (➖ 1.03x slower)

slot_pool

alloc_dealloc_1500 alloc_dealloc_4096 alloc_dealloc_128
8.29 ns (➖ 1.08x slower) 8.29 ns (➖ 1.08x slower) 8.31 ns (➖ 1.08x slower)

snapshot_files

load_snapshot_unverified
small 52.83 µs (➖ 1.01x slower)

virtq_readonly

slot_pool_segmented_fragmented slot_pool_segmented
262144 8.97 µs (➖ 1.08x slower) 9.03 µs (➖ 1.07x slower)
65536 2.57 µs (➖ 1.09x slower) 2.52 µs (➖ 1.01x faster)

virtq_readwrite

slot_pool_segmented_fragmented slot_pool_segmented
65536 8.48 µs (➖ 1.08x slower) 8.38 µs (➖ 1.03x slower)
8192 878.69 ns (➖ 1.05x slower) 854.70 ns (➖ 1.05x slower)
262144 35.34 µs (➖ 1.06x slower)
mshv3 / amd (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

encode_control decode_vec_bytes_copy
byte_chunks 1.00 µs (➖ 1.03x slower)
vec_bytes 710.79 ns (➖ 1.00x faster)
282.42 µs (➖ 1.05x faster)

payload_allocation

slot_pool_segmented
262144 720.25 ns (➖ 1.01x faster)
65536 201.16 ns (➖ 1.04x slower)

sandboxes

create_initialized_and_drop
medium 59.72 ms (➖ 1.01x faster)

slot_pool

alloc_dealloc_1500 alloc_dealloc_4096 alloc_dealloc_128
9.91 ns (➖ 1.02x slower) 9.76 ns (➖ 1.00x slower) 9.74 ns (➖ 1.01x slower)

snapshot_files

load_snapshot_unverified
small 85.26 µs (➖ 1.00x faster)

virtq_readonly

slot_pool_segmented_fragmented slot_pool_segmented
262144 10.12 µs (➖ 1.01x faster) 9.78 µs (➖ 1.02x slower)
65536 2.42 µs (➖ 1.04x faster) 2.26 µs (➖ 1.01x slower)

virtq_readwrite

slot_pool_segmented_fragmented slot_pool_segmented
65536 8.43 µs (➖ 1.18x faster) 8.47 µs (➖ 1.12x faster)
8192 1.28 µs (➖ 1.02x faster) 1.29 µs (➖ 1.02x slower)
262144 36.20 µs (➖ 1.07x faster)
mshv3 / intel (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

encode_control decode_vec_bytes_copy
byte_chunks 1.04 µs (➖ 1.12x slower)
vec_bytes 666.34 ns (➖ 1.00x slower)
788.59 µs (➖ 1.11x slower)

payload_allocation

slot_pool_segmented
262144 622.65 ns (➖ 1.00x slower)
65536 173.25 ns (➖ 1.04x slower)

sandboxes

create_initialized_and_drop
medium 69.12 ms (➖ 1.02x slower)

slot_pool

alloc_dealloc_1500 alloc_dealloc_4096 alloc_dealloc_128
9.68 ns (➖ 1.00x faster) 8.80 ns (➖ 1.00x slower) 8.81 ns (➖ 1.00x slower)

snapshot_files

load_snapshot_unverified
small 44.64 µs (➖ 1.07x faster)

virtq_readonly

slot_pool_segmented_fragmented slot_pool_segmented
262144 7.97 µs (➖ 1.01x faster) 8.01 µs (➖ 1.01x slower)
65536 2.31 µs (➖ 1.02x faster) 2.29 µs (➖ 1.01x faster)

virtq_readwrite

slot_pool_segmented_fragmented slot_pool_segmented
65536 7.55 µs (➖ 1.01x slower) 7.46 µs (➖ 1.03x faster)
8192 919.47 ns (➖ 1.04x faster) 919.85 ns (➖ 1.02x slower)
262144 38.37 µs (➖ 1.01x faster)
hyperv-ws2025 / amd (Windows) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

encode_control decode_vec_bytes_copy
byte_chunks 1.51 µs (➖ 1.28x slower)
vec_bytes 797.96 ns (➖ 1.01x slower)
2.07 ms (➖ 1.02x slower)

payload_allocation

slot_pool_segmented
262144 800.66 ns (➖ 1.01x slower)
65536 245.86 ns (➖ 1.06x slower)

sandboxes

create_initialized_and_drop
medium 81.55 ms (➖ 1.04x faster)

slot_pool

alloc_dealloc_1500 alloc_dealloc_4096 alloc_dealloc_128
10.26 ns (➖ 1.01x faster) 10.54 ns (➖ 1.01x slower) 10.29 ns (➖ 1.01x faster)

snapshot_files

load_snapshot_unverified
small 706.18 µs (➖ 1.06x faster)

virtq_readonly

slot_pool_segmented_fragmented slot_pool_segmented
262144 9.82 µs (➖ 1.05x slower) 9.18 µs (➖ 1.02x slower)
65536 2.43 µs (➖ 1.00x faster) 2.38 µs (➖ 1.01x slower)

virtq_readwrite

slot_pool_segmented_fragmented slot_pool_segmented
65536 8.91 µs (➖ 1.04x faster) 8.75 µs (➖ 1.00x slower)
8192 1.33 µs (➖ 1.04x faster) 1.29 µs (➖ 1.03x faster)
262144 41.70 µs (➖ 1.07x slower)
hyperv-ws2025 / intel (Windows) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

encode_control decode_vec_bytes_copy
byte_chunks 1.21 µs (➖ 1.00x slower)
vec_bytes 801.32 ns (➖ 1.03x slower)
4.25 ms (➖ 1.01x faster)

payload_allocation

slot_pool_segmented
262144 744.54 ns (➖ 1.00x faster)
65536 227.43 ns (➖ 1.06x slower)

sandboxes

create_initialized_and_drop
medium 145.64 ms (➖ 1.14x slower)

slot_pool

alloc_dealloc_1500 alloc_dealloc_4096 alloc_dealloc_128
10.69 ns (➖ 1.09x faster) 10.04 ns (➖ 1.26x faster) 10.69 ns (➖ 1.01x slower)

snapshot_files

load_snapshot_unverified
small 575.24 µs (➖ 1.00x faster)

virtq_readonly

slot_pool_segmented_fragmented slot_pool_segmented
262144 7.78 µs (➖ 1.00x slower) 7.81 µs (➖ 1.00x slower)
65536 2.39 µs (➖ 1.03x slower) 2.33 µs (➖ 1.00x faster)

virtq_readwrite

slot_pool_segmented_fragmented slot_pool_segmented
65536 8.58 µs (➖ 1.10x faster) 9.47 µs (➖ 1.12x slower)
8192 1.14 µs (➖ 1.11x faster) 1.12 µs (➖ 1.01x slower)
262144 43.75 µs (➖ 1.08x faster)

Reported by cargo ci bench-report --candidate run:37962439614 --config-file bench_report.toml.

This branch has not been deployed

No deployments
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.

2 participants